在 SDL 中将法线贴图应用于带纹理的四顶点多边形的最简单方法是什么?你必须创建一个着色器还是有更简单的方法?我在这里有我的代码,它创建了一个带有旋转卫星灯的带纹理的旋转立方体。
如果我还想将生成的纹理(tex_Norm = generateTexture())用作法线贴图,我需要对我的代码做哪些补充?
#include <windows.h>
#include <SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glext.h>
#include <math.h>
void initAll();
void setupBox();
void mainloop();
unsigned int generateTexture();
void handle_inputs();
void updateScreen();
void clean_up();
int scrWidth, scrHeight, flags;
bool bQuit = false;
float angle = 0.0f;
GLuint tex_Box, tex_Norm;
struct sVert
{
float x;
float y;
float z;
};
class cPolygon
{
public:
int v[4];
void fillverts(int v1, int v2, int v3, int v4) {
v[0] = v1;
v[1] = v2;
v[2] = v3;
v[3] = v4;
}
} p[6];
sVert pv[8];
int main(int argc, char *argv[])
{
initAll();
mainloop();
clean_up();
return 0;
}
void initAll()
{
scrWidth = 800;
scrHeight = 600;
SDL_InitSubSystem(SDL_INIT_VIDEO);
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
flags = SDL_OPENGL | SDL_ANYFORMAT ;
SDL_SetVideoMode(scrWidth, scrHeight, 16, flags);
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
gluPerspective( 45.0f, (GLfloat)scrWidth/(GLfloat)scrHeight, 1.0f, 500.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
SDL_WM_SetCaption( "Normal Mapping", NULL );
tex_Box = generateTexture();
tex_Norm = generateTexture();
setupBox();
}
void setupBox()
{
for (int z=0;z<2;z++)
for (int y=0;y<2;y++)
for (int x=0;x<2;x++)
{
pv[x+y*2+z*4].x = -1.0+x;
pv[x+y*2+z*4].y = -1.0+y;
pv[x+y*2+z*4].z = -1.0+z;
}
// Box object
p[0].fillverts (0, 1, 3, 2); // above
p[1].fillverts (4, 5, 1, 0); // behind
p[2].fillverts (6, 7, 3, 2); // in front
p[3].fillverts (5, 7, 3, 1); // right
p[4].fillverts (0, 2, 6, 4); // left
p[5].fillverts (7, 6, 4, 5); // below
}
unsigned int generateTexture()
{
BYTE data[128*128*3];
unsigned int id;
for (int x=0;x<128;x++)
for (int y=0;y<128;y++)
{
data[y*128*3+x*3+0] = x; // Red
data[y*128*3+x*3+1] = y; // Green
data[y*128*3+x*3+2] = 128-(abs(64-x)+abs(64-y)); // Blue
}
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
return id;
}
void mainloop()
{
while(bQuit == false)
{
handle_inputs();
updateScreen();
angle += 1.5f;
Sleep(50);
}
}
void handle_inputs()
{
SDL_PumpEvents();
Uint8 * keystate = SDL_GetKeyState(NULL);
if(keystate[SDLK_ESCAPE]) bQuit = true;
}
void updateScreen()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
glTranslatef(0.0f, 0.0f, -3.0f);
glRotatef(-angle*2.0, 1.0f, 1.0f, 1.0f);
// Setup a light source
float lpos[] = {0.0, 0.0, 2.0, 1.0}; // position
float ldif[] = {1.0, 1.0, 1.0, 1.0}; // diffuse
float lamb[] = {0.3, 0.3, 0.2, 1.0}; // ambient
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
glLightfv(GL_LIGHT0, GL_DIFFUSE, ldif);
glLightfv(GL_LIGHT0, GL_AMBIENT, lamb);
glPopMatrix();
glPushMatrix();
glTranslatef(0.5f, 0.5f, -3.0f);
glRotatef(angle, 1.0f, 1.0f, 1.0f);
// Draw box object
glBindTexture(GL_TEXTURE_2D, tex_Box);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
for(int pi=0; pi<6; pi++)
for(int vi=0; vi<4; vi++)
{
switch(vi) {
case 0: glTexCoord2d(0.0,2.0); break;
case 1: glTexCoord2d(0.0,0.0); break;
case 2: glTexCoord2d(2.0,0.0); break;
case 3: glTexCoord2d(2.0,2.0); break; };
glVertex3f( pv[ p[pi].v[vi] ].x,
pv[ p[pi].v[vi] ].y,
pv[ p[pi].v[vi] ].z );
};
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glFinish();
SDL_GL_SwapBuffers();
}
void clean_up()
{
SDL_QuitSubSystem(SDL_INIT_VIDEO);
glDeleteTextures(1, &tex_Box);
glDeleteTextures(1, &tex_Norm);
SDL_Quit();
}