[OpenGL] Как использовать blending?
а) посортировать все полупрозрачные примитивы (т.е. все грани своей модельки, все модельки содержащие полупрозрачные грани) и выводить их back-to-front. Иначе не получится - потому что блендинг с такой функцией блендинга не коммутативен относительно порядка вывода граней (о как сказанул
б) Использовать glBlendFunc(GL_SRC_ALPHA, GL_ONE); вместо glDepthfunc(GL_ALWAYS) лучше все-таки сказать glDepthMask(0). - тебе же нужно не игнорировать Z, а просто туда не писАть! После чего пограццо с освещением и текстурами, так чтобы это выглядело достаточно реалистично.
Полупрозрачные грани в обоих случаях надо выводить ПОСЛЕ всей остальной сцены. Вырубать запись в буфер глубины нужно только в случае б). Не забудь сказать glDisable(GL_CULL_FACE);
Вроде все.
ЗЫ: Когда включишь освещение, можешь очень удивиццо, куда делась вся альфа. Отвечаю: альфа проиппалась, чтобы альфа не проиппалась, юзай
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
спасибо попробую
у меня тысчи 2-5 полигонов...
в каждый момент их сортировать... потянет производительность?
Ну... Наверное да. Главное - сортируй правильно. Типа qsort, и индексы, и все такое. Еще маза загонять их в vertex array, а выводить через index array, потому что если ты их ручками через glVertexXXX будешь делать, то не потянет точно.
А как игрушки это делают? Так и делают небось (ну, ясен пень, немного хитрее, но)
в контре вообще почти нет
Но! Поскольку контра на движке халвы, которая на движке ку2, которая на движке ку1, которая на BSP деревьях, статический объект "уровень" можно считать пресортированным по Z по любым направлениям.
Гораздо интересней вопрос - как варкрафт 3 не загибается нахх, если у них практически у каждого юнита в текстурах альфа-дырки присутствуют?
А вот это как раз не проблема. Вначале можно отсортировать по z всех юнитов, а затем для каждого юнита проделать ту же операцию. Вполне неплохое приближение. Они же маленькие Да, а как связаны BSP деревья и отсортированность по Z? Я чего-то не догоняю.
весь уровень разбит на выпуклые многогранники (в выпуклом многограннике все равно в каком порядке грани рисовать а сами многогранники могут быть связаны либо общими гранями (тогда порталы получаются, либо упорядочены в двоичное дерево, тогда BSP)
Проблема только в том сколько листьев рисовать, кажется Q1 хранил списки видимых, которые рендерелись на этапе рисования уровня (и при том довольно долго)
ЗЫ: Когда включишь освещение, можешь очень удивиццо, куда делась вся альфа. Отвечаю: альфа проиппалась, чтобы альфа не проиппалась, юзайлучше всё же не так
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
лучше выставлять альфу посредством материала
GLfloat m_emissive[4] = { 0.0f, 0.0f, 0.0f, 0.5f };
GLfloat m_diffuse[4] = { 0.2f, 0.2f, 0.2f, 0.5f };
GLfloat m_specular[4] = { 0.8f, 0.8f, 0.8, 0.5f };
GLfloat m_ambient[4] = { 0.8f, 0.8f, 0.8f, 0.5f };
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, m_emissive);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, m_ambient);
glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS, 10);
кстати, выставляя разную альфу для разных составляющих, можно получить разные презабавнейшие эффекты. правда, как это юзать, я так и не придумал %)
Поскольку контра на движке халвы, которая на движке ку2, которая на движке ку1, которая на BSP деревьях, статический объект "уровень" можно считать пресортированным по Z по любым направлениям.1)
эй
а при чём тут сортировка по Z?
2)
я могу ошибаться, но
начиная с ку2, в основе представления сцены лежат не бсп-деревья, а несколько другой подход
там на этапе препроцессинга дико сложным алгоритмом (описание занимает 60 страниц А4 мелким шрифтом) строится для каждой грани список граней, потенциально её закрывающих хоть с одной из точек наблюдения
и из этого говна строится (не помню, как называется)-дерево
хотя бсп там, конечно, тоже юзается
посмотреть точно можно в книжке Борескова-Шикина "Полигональные модели" или в новой книжке Борескова (ни того, ни другого просто нет под рукой сейчас)
2) ну типа мб.
вот именно, что практически
грани, содержащиеся в каждой ноде всё равно сортировать надо
или же строить бсп-дерево, где по одной грани на узел
а это глупо
т.е. например свою вставить можно через glLoadMatrix
а ихнюю вытащить можно?
особенно учитывая, на что это был ответ %)
но, наверное, ты всё же вот об этом:
double m[16];
glGetDoublev(GL_MODELVIEW_MATRIX, m);
то же самое для проективной и текстурной матриц
я уже заколебался!
никак по Z отвортировать не могу полигончики...
хотел через эту матрицу не получается...
считал по своей формуле которую вывел рисует но с глюками, плюс свет моргает и отключаеться...
с матрицей не глючит но и Z не верно высчитывает...
не по одной грани на узел, а по выпуклому многограннику на узел бсп-дерева, такой многогранник все равно в каком порядке рисовать если у каждой грани задана нормаль.
Проблема в том сколько узлов рисовать, вот именно это очень долго просчитывается, но никакого отношения к сортировке по З не имеет
P.S. или поправьте меня если я не прав. (c) Goblin Не помню пьяная была когда дракона писала, разве их всех упомнишь.
Типа. А взять расстояние от середины треугольника (среднее арифметическое его вершин) до позиции камеры уже не модно? Типа что настоящие пацаны умножают на матрицы и ффсе такое.... =)
меня это тоже всегда забавляло
вместо того, чтобы умножить на матрицу положение камеры, умножают положения всех центров
самое интересное, что во многих тутах так же написано
может, это мировой заговор?
не важно как идем главное результат в драконе я так и делал.
Берешь скалярное произведение вектора В = "Центр Объекта" - "Позиция Камеры" самого с собой. Сортируешь по этой величине. ААААА! Какие матрицы! ЗАГОВОР!
только нагрузка на проц раз в 5 больше, а так всё в порядке
А... это ты завхозу ответил...
"Позиция Камеры" == (0, 0, 0, 1) * матрицу
посмотри, кому я ответил, йопт
Znew = a31*x + a32*y + a33*z + a34*1
но т.к. m[16] то Znew = a[3]*x + a[7]*y + a[11]*z + a[15];
правда нихуя не получилось.
MatrixMode - MODELVIEW,
матрицу получаю после
pushmatrixа
и Translate и 2х Rotate
хз, буду в понедельник втыкать дальше
ну что ты мозг компостируешь, а?
тебе ж сказали, как правильно делать
и ваще
только что попробовал с матрицами
dirty-coding, конечно
написано через жопу и всё такое
но работает
так что не знаю, чего у тебя там не так
double cur_modelview[16];
int CompareZ(const void *el1, const void *el2)
{
tFace face1 = (*tFace *) el1;
tFace face2 = (*tFace *) el2;
double f1_x = face1.center[0];
double f1_y = face1.center[1];
double f1_z = face1.center[2];
double f2_x = face2.center[0];
double f2_y = face2.center[1];
double f2_z = face2.center[2];
double z1 = f1_x * cur_modelview[2] + f1_y * cur_modelview[6] +
f1_z * cur_modelview[10] + cur_modelview[14];
double z2 = f2_x * cur_modelview[2] + f2_y * cur_modelview[6] +
f2_z * cur_modelview[10] + cur_modelview[14];
if z1 - z2 <= 0.01) && (z1 - z2 >= -0.01
return 0;
else if (z1 < z2)
return -1;
else // if (z1 > z2)
return 1;
}
void cModel::SortByZ(void)
{
glGetDoublev(GL_MODELVIEW_MATRIX, cur_modelview);
changed = 1;
for (int c = 0; c < 16; c++)
{
if (cur_modelview[c] != prev_modelview[c]) changed = 0;
}
if (changed)
{
for(int i = 0; i < model_3ds.numOfObjects; i++)
{
if(model_3ds.pObject.size <= 0) break;
t3DObject *pObject = &model_3ds.pObject[i];
qsort(pObject->pFaces,
pObject->numOfFaces,
sizeof(tFace
CompareZ);
}
}
}
Это означает, что тебе в обязательном порядке придется использовать даблы, и то у тебя будут разные забавные глюки.
Если уж хочется использовать матрицу, то тогда надо юзать W из результата, он вроде как поприятней.
Но! Считать расстояние до камеры ручками гораздо удобнее и БЫСТРЕЕ (большие буквы - это нлп
Кста, вот ето трогательное 0.01 в Павликовском коде меня прям растрогало! Нифига ж работать не будет, если объект удалить чуть-чуть!
Кста, вот ето трогательное 0.01 в Павликовском коде меня прям растрогало!
ну дык
dirty-coding, конечно
Как на полигон (пока хотя бы на четырёхугольник)
натянуть текстурку, ну ни хера не выходит, и игруха без этого не смотрится....
в манах ни фига нет, делаю как по книжки - и ни фига (сначала читаю бмп,
потом редактирую текстуру - всё честь-по-чести, размеры - степени двойки,
3 байта на цвет (без альфа разрешаю двумерные текстуры, привязываю
координаты к вершинам - и ни фига). Киньте, плиз, блок текста (работающий в линксе,
желательно а то третий день дрочусь...
(ну ооочень лень сейчас всю эту кучу галиматьи из проги вырезать и выкладывать)
typedef class tMainScene:public GlObject{
public:
float Height;
float Radius;
char *Texture;
tMainScene(float x,float y,float z,float h,float r,int n,char* TextureFileName)
{int a,s;
FILE *TexF=fopen(TextureFileName,"rb");
Center.x=x;
Center.y=y;
Center.z=z;
Radius=r;
Height=h;
Resolution=n;
fseek(TexF,54,SEEK_SET);
Texture=new char [256*512*3];
for(a=255;a>=0;a--)
for(s=0;s<512;s++)
{fread(Texture+a*512*3+s*3+2,1,1,TexF);
fread(Texture+a*512*3+s*3+1,1,1,TexF);
fread(Texture+a*512*3+s*3,1,1,TexF);
}
glEnable(GL_TEXTURE_2D);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glTexImage2D(GL_TEXTURE_2D,1,3,512,256,0,GL_RGB,GL_BYTE,Texture);
//glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WARP_S,1);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
//glEnable(GL_TEXTURE_2D);
}
void Generate
{GLfloat color[4];
float cx=Center.x,cy=Center.y,cz=Center.z,r=Radius,h=Height;
int n=Resolution,a;
float k=K;
//glEnable(GL_TEXTURE_2D);
glBegin(GL_QUAD_STRIP);
color[0]=k;//sin(0)*k;
color[1]=k;//cos(0)*k;
color[2]=k;
color[3]=0.1;
//glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,color);
for(a=0;a<=n;a++)
{glTexCoord2d(sin(pi*a/n0);
glVertex3f(cx+r*cos(pi*2*a/ncy+h,cz+r*sin(pi*2*a/n;
glTexCoord2d(sin(pi*a/n1);
glVertex3f(cx+r*cos(pi*2*a/ncy-h,cz+r*sin(pi*2*a/n;
color[0]=k;//sin(pi*2*a/n)*k;
color[1]=k;//cos(pi*2*a/n)*k;
color[2]=k;
color[3]=0.1;
//glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,color);
}
glEnd;
}
};
Файл - bmp-шка 512*256*24(! не знал, что такое бывает)
for(a=255;a>=0;a--)
for(s=0;s<512;s++)
{fread(Texture+a*512*3+s*3+2,1,1,TexF);
fread(Texture+a*512*3+s*3+1,1,1,TexF);
fread(Texture+a*512*3+s*3,1,1,TexF);
}
ты формат бмп-файла в глаза видел?
Formats.h
#ifndef __FORMATS_H
#define __FORMATS_H
// BMP file format definition
#pragma pack(1)
struct BMPHeader {
short type; // File type = 0x4D42
int size;
short reserved1;
short reserved2;
int offset; // Offset from file start to bitmap data
};
struct BMPInfoHeader {
int size; // Size of this structure in bytes
int width;
int height;
short planes; // Should be equal to 1
short bitsPerPixel;
unsigned compression; // Compression flags ( 0 - no compression )
unsigned imageSize; // Size of image in bytes
int xPelsPerMeter;
int yPelsPerMeter;
int clrUsed;
int clrImportant;
};
struct BMPPaletteItem {
unsigned char blue;
unsigned char green;
unsigned char red;
unsigned char unused;
};
#pragma pack
#endif
BmpLoad.h
#ifndef __BMPLOAD_H
#define __BMPLOAD_H
unsigned char *LoadTrueColorBMPFile(const char *path,int *width,int *height);
#endif
BmpLoad.cpp
#include"formats.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
unsigned char *LoadTrueColorBMPFile(const char *path,int *width,int *height)
{
unsigned char *result = NULL;
FILE *in = fopen(path,"rb");
if(!in)
return NULL;
BMPHeader hdr;
fread(&hdr,sizeof(hdr1,in);
if(hdr.type != 0x4D42) // Not a bitmap file at all
return NULL;
BMPInfoHeader infoHdr;
fread(&infoHdr,sizeof(infoHdr1,in);
if(infoHdr.bitsPerPixel != 24) // Not a truecolor bitmap
return NULL;
if(infoHdr.compression) // Compressed bitmap
return NULL;
ifresult = new unsigned char[infoHdr.width*infoHdr.height*3]) == NULL)
return NULL;
fseek(in,hdr.offset-sizeof(hdr)-sizeof(infoHdrSEEK_CUR);
unsigned char *dst = result;
for(int y=0;y<infoHdr.height;y++) {
for(int x=0;x<infoHdr.width;x++) {
dst[2] = fgetc(in);
dst[1] = fgetc(in);
dst[0] = fgetc(in);
dst += 3;
}
for(x=0;x<4-(infoHdr.width&3&3);x++) // Skip alignment bytes
fgetc(in);
}
fclose(in);
*width = infoHdr.width;
*height = infoHdr.height;
return result;
}
cTexture.h
#ifndef _____C_____TEXTURE________H____
#define _____C_____TEXTURE________H____
class cTexture
{
private:
unsigned int m_tex_handle;
public:
cTexture(const char *file);
~cTexture;
void Bind(void);
};
#endif // _____C_____TEXTURE________H____
cTexture.cpp
#include "cTexture.h"
#ifdef _WIN32
#include <windows.h>
#endif
#include <gl/gl.h>
#include <gl/glu.h>
#include "BmpLoad.h"
#include <stdio.h>
cTexture::cTexture(const char *file)
{
m_tex_handle = 0;
printf("Loading %s ", file);
unsigned char *tex_bits;
int width, height;
tex_bits = LoadTrueColorBMPFile(file, &width, &height);
if (tex_bits == NULL)
{
printf("Error!\n");
exit(1);
}
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glGenTextures(1, &m_tex_handle);
glBindTexture(GL_TEXTURE_2D, m_tex_handle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
gluBuild2DMipmaps
(
GL_TEXTURE_2D,
3,
width,
height,
GL_RGB,
GL_UNSIGNED_BYTE,
tex_bits
);
delete [] tex_bits;
printf("Done!\n");
}
cTexture::~cTexture
{
if (m_tex_handle != 0)
glDeleteTextures(1, &m_tex_handle);
}
void cTexture::Bind(void)
{
glBindTexture(GL_TEXTURE_2D, m_tex_handle);
}
А дело, наверное, в том, что я glBindTexture не юзал.... Попробою. Thnx
как минимум ты алигменты в конце строчек не учитываешь
По-любому, какая-то кака всё равно бы натянулась на полигон, даже если не так читать текстуру.
но я это не к тому
это я к заявлению, что он в курсе, какой там формат
2 А alignment'ы... Ну, ёб, ну, нет их там, я смотрел (512x256+0+0)... К тому же, как ни странно, 512*3 делится на 4 вроде бы нацело...
Дело-то не в этом, мне надо было не напряжно bmp-шку считать и проверить...
И ещё. Это всё круто, конечно, но хотелось бы весь блок.... То есть, может, меня глючит не при создании текстуры, а при наложении,
так как gluBuild2DMipmaps (его сначала пробовал) говорит, что всё зашибись, текстура есть...
Вот.
А не мобыть сначала сгенерить текстурку в памяти какой-нить процедуркой, чтобы отделить 2 различные проблемы - создание текстур и наложение текстур?
бля, ебать у меня же такая детская ошибка! забыл что первый элемент массива с индексом 0 ебать, спутал меня манул по OpenGL, седня проверю
cForest::cForest(double side)
{
m_tree_tex[0] = new cTexture("Data\\tree1.bmp", true);
m_tree_tex[1] = new cTexture("Data\\tree2.bmp", true);
m_tree_tex[2] = new cTexture("Data\\tree3.bmp", true);
m_tree_tex[3] = new cTexture("Data\\tree4.bmp", true);
int iters = 4;
int n = 1;
for (int p = 0; p < iters; p++)
n <<= 1;
n++;
cMountain m;
m.Generate(side, iters, 0.0, 1.0, 4);
float **heights = m.GetHeights;
double cell = side / n;
m_size[0] = m_size[1] = m_size[2] = m_size[3] = 0;
m_ind[0] = m_ind[1] = m_ind[2] = m_ind[3] = NULL;
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j < n - 1; j++)
{
double c = heights[i][j] + heights[i + 1][j] + heights[i][j + 1] + heights[i + 1][j + 1];
c /= 4;
int ntr = int (c * 6);
for (int k = 0; k < ntr; k++)
{
double *vec = new double [2];
vec[0] = i * cell + (rand / (double)RAND_MAX) * cell;
vec[1] = j * cell + (rand / (double)RAND_MAX) * cell;
m_coords.push_back(vec);
int t = rand % 4;
(m_size[t])++;
m_ind[t] = (int *) realloc(m_ind[t], m_size[t] * sizeof(int;
m_ind[t][m_size[t] - 1] = m_coords.size - 1;
}
}
}
}
cForest::~cForest
{
}
void cForest::Draw(void)
{
glPushAttrib(GL_TEXTURE_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.4);
int size = m_coords.size;
double w = 0.06;
double w2 = w / 2;
double angle = g_roty * M_PI / 180;
double ca = cos(angle);
double sa = sin(angle);
glColor4d(0, 1, 0, 1);
glEnable(GL_TEXTURE_2D);
for (int t = 0; t < 4; t++)
{
m_tree_tex[t]->Bind;
for (int i = 0; i < m_size[t]; i++)
{
double x1 = m_coords[m_ind[t][i]][0] - w2 * ca;
double x2 = m_coords[m_ind[t][i]][0] + w2 * ca;
double z1 = m_coords[m_ind[t][i]][1] - w2 * sa;
double z2 = m_coords[m_ind[t][i]][1] + w2 * sa;
glBegin(GL_QUADS);
glTexCoord2d(0, 0);
glVertex3d(x1, 0, z1);
glTexCoord2d(1, 0);
glVertex3d(x2, 0, z2);
glTexCoord2d(1, 1);
glVertex3d(x2, w, z2);
glTexCoord2d(0, 1);
glVertex3d(x1, w, z1);
glEnd;
}
}
glPopAttrib;
}
gluBuild2DMipmaps (его сначала пробовал) говорит, что всё зашибись
Sorry. Это Re на
А не мобыть сначала сгенерить текстурку в памяти какой-нить процедуркой, чтобы отделить 2 различные проблемы - создание текстур и наложение текстур?
ты это к чему?
Ну, это, текстура создана и размещена.... Или я не понимаю, чего сия процедура делает....
ты мой кусок кода посмотрел?
всё ещё не работает?
если всё обстоит именно так -- давай сюда исходники
вечером посмотрю
Во-первых, я его увидел 10 минут назад, а во-вторых, у меня щас комп (мой, а не этот) занят.
В-третьих, я не флудер.
мне правда интересно
Нулевой..... Что-то у меня всё-таки кривое....
Вот-вот.... и glBindTexture вставил (это, оказывается, вовсе не то, и вовсе не нужно) - ни фига.
У меня возникает странное ощущение... Ну... От того, что ты надеялся, что все без glBindTexture будет работать, а еще от того, что "это, оказывается, вовсе не то, и вовсе не нужно".
Мне кажется, что твоя картина мира совершенно не совпадает с openGL в части использования текстур.
Читай павликовский код и мануали. Особое внимание обрати на описание и использование функции glBindTexture.
дай ты мне свои сорцы уже наконец!
Правда, я до сих пор не понял, почему раньше не шло (ну, pablitoвский код)...
А fj, конечно, прав... Я OGL юзаю всего неделю....
обращайся, если что
Оставить комментарий
lord2476
какие тонкости есть в blending'е?я хочу использовать glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
но! если модель развернуть на 90 градусов, то задняя кртинка полностью прозрачна, и через неё видна передняя
использую glDethfunc(GL_ALWAYS) т.к. с другими сзади вообще нету прозрачности.
использую текстуры