Программа имитации освещения Фонга с помощью мультитекстурирования
#include "stdafx.h" #include "FS.h" #include "GLScene.h" #pragma warning(disable: 4305 4309 4244) CGLScene::CGLScene() { rect.left = 0; rect.right = 640; rect.top = 0 ; rect.bottom = 480; texdim = 128; objangle[0] = 0.f; objangle[1] = 0.f; objpos[0] = 0.f; objpos[1] = 0.f; color[0] = 1.f; color[1] = 1.f; color[2] = 1.f; color[3] = 1.f; zero[0] = 0.f; zero[1] = 0.f; zero[2] = 0.f; zero[3] = 1.f; one[0] = 1.f; one[1] = 1.f; one[2] = 1.f; one[3] = 1.f; lighttex = 0; lightpos[0] = 0.f; lightpos[1] = 0.f; lightpos[2] = 1.f; lightpos[3] = 0.f; lightchanged[0] = GL_TRUE; lightchanged[1] = GL_TRUE; } CGLScene::~CGLScene() { if (lighttex) delete [] lighttex; } void CGLScene::Resize(int cx, int cy) { rect.left = 0; rect.top = 0; rect.right = cx; rect.bottom = cy; glViewport(0, 0, rect.right - rect.left, rect.bottom - rect.top); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-100., 100., -100., 100., 300., 600.); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0., 0., 450., 0., 0., 0., 0., 1., 0.); } void CGLScene::MakeHighlight(int intens) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); // предполагаем, что ModelView glLoadIdentity(); glTranslatef(0.f, 0.f, -texdim/2.f); glMatrixMode(GL_PROJECTION); // подготавливаемся к параллельному проецированию glPushMatrix(); glLoadIdentity(); glOrtho(-texdim/2., texdim/2., -texdim/2., texdim/2., 0., texdim/2.); glPushAttrib(GL_LIGHTING_BIT|GL_VIEWPORT_BIT); // изменяем размеры Viewport'a под размеры текстуры glViewport(0, 0, texdim, texdim); glEnable(GL_LIGHTING); // включаем освещение glLightfv(GL_LIGHT0, GL_DIFFUSE, zero); glLightfv(GL_LIGHT0, GL_POSITION, lightpos); // положение источника glMateriali(GL_FRONT, GL_SHININESS, intens); // задаём степень светимости glMaterialfv(GL_FRONT, GL_AMBIENT, zero); // остальные параметры -> ноль glMaterialfv(GL_FRONT, GL_DIFFUSE, zero); glMaterialfv(GL_FRONT, GL_SPECULAR, color); // цвет glDisable(GL_TEXTURE_2D); glCallList(1); // рисуем блик glEnable(GL_TEXTURE_2D); // восстанавливаем установки GL glPopAttrib(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glReadPixels(0, 0, texdim, texdim, GL_RGB, GL_FLOAT, lighttex); // читаем содержимое Framebuffer'a glBindTexture(GL_TEXTURE_2D, HIGHLIGHT_TEX); // присвоить созданной текстуре идентификатор glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, texdim, texdim, GL_RGB, GL_FLOAT, lighttex); } void CGLScene::Render() { objangle[X]+=5.0f; objangle[Y]+=7.0f; //objangle[X]=60; objangle[Y]=90; static GLfloat ax=0.0f, ay=0.0f, az=0.0f; GLfloat ca, sa; GLfloat x=lightpos[0], y=lightpos[1], z=lightpos[2]; ax+=2.0f*M_PI/180.0f; ay+=3.0f*M_PI/180.0f; az+=4.0f*M_PI/180.0f; ca=cos(az); sa=sin(az); // вращение вокруг оси OZ lightpos[0]=ca - sa; lightpos[1]=sa + ca; lightchanged[0]=GL_TRUE; lightchanged[1]=GL_TRUE; RenderTexHighlight(); // на каждом кадре - пересчёт блика } void CGLScene::RenderTexHighlight() { // положение источника изменилось if(lightchanged[UPDATE_TEX]) { MakeHighlight(128); lightchanged[UPDATE_TEX] = GL_FALSE; } if(lightchanged[UPDATE_OGL]) { glLightfv(GL_LIGHT0, GL_POSITION, lightpos); lightchanged[UPDATE_OGL] = GL_FALSE; } glPushMatrix(); // предполагаем, что ModelView glTranslatef(objpos[X], objpos[Y], 0.f); glRotatef(objangle[Y], 0.f, 1.f, 0.f); glRotatef(objangle[X], 1.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // рисуем диффузную составляющую света glEnable(GL_LIGHTING); glBindTexture(GL_TEXTURE_2D, SURF_TEX); glCallList(2); glDisable(GL_LIGHTING); // блик glClearColor(0.75, 0.75, 0.75, 1); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, HIGHLIGHT_TEX); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glDepthFunc(GL_LEQUAL); glCallList(2); glDepthFunc(GL_LESS); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_BLEND); glPopMatrix(); // SwapBuffers(wglGetCurrentDC()); glFlush(); } void CGLScene::PrepareGL() { glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); // параметры автогенерации координат текстуры glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glMateriali(GL_FRONT, GL_SHININESS, 128); glCullFace(GL_BACK); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0, 1.0); lightchanged[UPDATE_TEX] = GL_TRUE; lightchanged[UPDATE_OGL] = GL_TRUE; // генерируем простую текстуру int texwid = 128, texht = 128; GLbyte *tex=new GLbyte[texwid * texht * 3]; GLbyte *ptr=tex; for (int i = 0; i < texht; ++i) { for (int j = 0; j < texwid; ++j) { if ((i ^ j) & 8) {ptr[0] = 0xff; ptr[1] = 0xff; ptr[2] = 0xff;} else {ptr[0] = i*512/texht; ptr[1] = j*512/texwid; ptr[2] = 196;} ptr += 3; } } gluBuild2DMipmaps(GL_TEXTURE_2D, 3, texwid, texht, GL_RGB, GL_UNSIGNED_BYTE, tex); delete [] tex; lighttex = new GLfloat[texdim * texdim * 3]; GLUquadricObj *q; q=gluNewQuadric(); glNewList(1, GL_COMPILE); gluSphere(q, (GLdouble)texdim/2., 50, 50);// сфера для блика glEndList(); gluDeleteQuadric(q); GLUquadricObj *quadric = gluNewQuadric(); gluQuadricTexture(quadric, GL_TRUE); glNewList(2, GL_COMPILE); gluSphere(quadric, 70., 20, 20);// сфера, выводимая в буфер кадра glEndList(); gluDeleteQuadric(quadric); glClearColor(1.0, 1.0, 1.0, 1.0); }