2014-04-05 5 views
1

SDL의 텍스처가있는 4 개의 정점 폴리곤에 노멀 맵을 적용하는 가장 간단한 방법은 무엇입니까? 셰이더를 만들어야합니까, 아니면 더 간단한 방법이 있습니까? 회전하는 위성 라이트로 텍스처 큐브를 만드는 내 코드를 여기 있습니다.SDL OpenGL 일반 매핑

생성 된 텍스처 (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(); 
} 

답변

2

죄송합니다. 최신 OpenGL 기능을 사용하려면 최신 OpenGL이 필요합니다. 즉, 셰이더를 의미합니다. : 즉, 쉐이더에서 모든 조명을 수동으로 처리해야하므로 프로그램이 상당히 복잡해 지지만 멋진 이미지를 얻는 데 드는 비용입니다.

자세한 방법을 설명합니다. 노멀 매핑은 여기에 맞지 않을 것이지만, 아주 좋은 자습서 예를 http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-13-normal-mapping/를 들어, 거기에있다.

행운을 빕니다!

+0

일부 Shader 자습서를 읽었지만 이해하지 못했습니다. "모든 조명이 쉐이더에서 수동으로 수행되어야 함을 의미합니다."라고 말하면 대답에 뭔가가 있습니다. 실제로 저는 예제에서 Shader를 사용하여 간단한 방법으로 진행하는 튜토리얼을 찾지 못했고 셰이더를 사용하여 작업해야하는 부분의 차이점을 설명했습니다. 셰이더에서도 메쉬에 텍스처를 적용하고 있습니까? 셰이더를 구현 한 후에 내 "updateScreen()"함수가 많이 남지는 않겠습니까? – GlamCasvaluir

1

를 GLSL의 세계에 몇 시간 모험이 문제의 해답의 도움 후 : SDL OpenGL in C++, Texture Shader missing the texture

... 마침내 m에서 표준 맵을 만들었습니다. y가 텍스처를 생성했습니다. 결과는 다음과 같습니다.

#include <windows.h> 
#include <SDL.h> 

#include <GL/glew.h> 
#include <GL/glu.h> 
#include <GL/glut.h> 
#include <stdio.h> 

#include <math.h> 
#include <string> 

using namespace std; 
#define LOG_SIZE 10000 

void   initAll(); 
void   setupBox(); 
void   mainloop(); 
unsigned int generateTexture(); 
void   handle_inputs(); 
void   updateScreen(); 
void   clean_up(); 
void   dbpf(int, const char *, ...); 

int    scrWidth, scrHeight, flags; 
bool   bQuit = false; 
float   angle = 0.0f; 

va_list   m; 
int    db_threashold = 0; 
GLint   status; 
GLchar   elog[LOG_SIZE]; 
GLint   rLength = 0; 

GLuint   tex_Box, tex_Norm; 

std::string  vertex_source, fragment_source; 
GLuint   shader_program, vertex_shader, fragment_shader; 

GLuint   vao, vbo; 

const char  *source; 
int    length; 

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; 

    vertex_source = 
     "#version 330\n" 
     "in vec3 Position;\n" 
     "in vec2 TexCoord;\n" 
     "out vec3 oColor;\n" 
     "out vec2 oTexcoord;\n" 
     "void main() {\n" 
     " oTexcoord = TexCoord;\n" 
     " gl_Position = gl_ModelViewProjectionMatrix*vec4(Position, 1.0);\n" 
     "}\n"; 

    fragment_source = 
     "#version 330\n" 
     "in vec2 oTexcoord;\n" 
     "out vec4 oColor;\n" 
     "uniform sampler2D tex;\n" 
     "uniform sampler2D tex_norm;\n" 
     "void main() {\n" 
     " vec4 lightpos = normalize(-gl_ModelViewProjectionMatrix*vec4(1.0, -1.0, -1.5, 1.0));\n" 
     " vec3 tmpNorm = normalize(texture2D(tex_norm, oTexcoord).rgb * 2.0 - 1.0);\n" 
     " float difuse = max(dot(tmpNorm, lightpos.xyz), 0.0);\n" 
     " vec3 tmpcolor = difuse * texture2D(tex, oTexcoord).rgb;\n" 
     " oColor = vec4(tmpcolor, 1.0);\n" 
     "}\n"; 

    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); 

    SDL_WM_SetCaption("Normal map", NULL); 

    glewInit(); 

    // vertex shader 
    vertex_shader = glCreateShader(GL_VERTEX_SHADER); 
    source = vertex_source.c_str(); 
    length = vertex_source.size(); 
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader); 

    glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status); 
    glGetShaderInfoLog(vertex_shader, LOG_SIZE, &rLength, elog); 
    dbpf(10, "Compile vertex log: \n %s \n", elog); 

    // fragment shader 
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 
    source = fragment_source.c_str(); 
    length = fragment_source.size(); 
    glShaderSource(fragment_shader, 1, &source, &length); 
    glCompileShader(fragment_shader); 

    glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status); 
    glGetShaderInfoLog(fragment_shader, LOG_SIZE, &rLength, elog); 
    dbpf(10, "Compile fragment log: \n %s \n", elog); 

    // create program 
    shader_program = glCreateProgram(); 

    // attach shaders 
    glAttachShader(shader_program, vertex_shader); 
    glAttachShader(shader_program, fragment_shader); 

    // link the program and check for errors 
    glLinkProgram(shader_program); 
    glGetProgramiv(shader_program, GL_LINK_STATUS, &status); 
    glGetProgramInfoLog(shader_program, LOG_SIZE, &rLength, elog); 
    dbpf(10, "Link log: \n %s \n", elog); 

    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 

    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 

    setupBox(); 

    GLfloat vd[6*5*6]; 

    for(int pi=0; pi<6; pi++) 
    { 
     vd[pi*30+ 0] = pv[ p[pi].v[0] ].x; 
     vd[pi*30+ 1] = pv[ p[pi].v[0] ].y; 
     vd[pi*30+ 2] = pv[ p[pi].v[0] ].z; 

     vd[pi*30+ 3] = 0.0; 
     vd[pi*30+ 4] = 1.0; 

     vd[pi*30+ 5] = pv[ p[pi].v[1] ].x; 
     vd[pi*30+ 6] = pv[ p[pi].v[1] ].y; 
     vd[pi*30+ 7] = pv[ p[pi].v[1] ].z; 

     vd[pi*30+ 8] = 0.0; 
     vd[pi*30+ 9] = 0.0; 

     vd[pi*30+10] = pv[ p[pi].v[2] ].x; 
     vd[pi*30+11] = pv[ p[pi].v[2] ].y; 
     vd[pi*30+12] = pv[ p[pi].v[2] ].z; 

     vd[pi*30+13] = 1.0; 
     vd[pi*30+14] = 0.0; 

     vd[pi*30+15] = pv[ p[pi].v[0] ].x; 
     vd[pi*30+16] = pv[ p[pi].v[0] ].y; 
     vd[pi*30+17] = pv[ p[pi].v[0] ].z; 

     vd[pi*30+18] = 0.0; 
     vd[pi*30+19] = 1.0; 

     vd[pi*30+20] = pv[ p[pi].v[2] ].x; 
     vd[pi*30+21] = pv[ p[pi].v[2] ].y; 
     vd[pi*30+22] = pv[ p[pi].v[2] ].z; 

     vd[pi*30+23] = 1.0; 
     vd[pi*30+24] = 0.0; 

     vd[pi*30+25] = pv[ p[pi].v[3] ].x; 
     vd[pi*30+26] = pv[ p[pi].v[3] ].y; 
     vd[pi*30+27] = pv[ p[pi].v[3] ].z; 

     vd[pi*30+28] = 1.0; 
     vd[pi*30+29] = 1.0; 
    } 

    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*5*6, vd, GL_STATIC_DRAW); 

    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 

    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 

    tex_Box = generateTexture(); 
    tex_Norm = generateTexture(); 
} 

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; 
    } 

    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); 
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, data); 
    glGenerateMipmap(GL_TEXTURE_2D); 

    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(); 

    gluLookAt (2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 

    // use the shader program 
    glUseProgram(shader_program); 

    // bind the vao 
    glBindVertexArray(vao); 

    // rotation 
    glRotatef(angle, 1.0, 0.0, 0.0); //rotate on the x axis 
    glRotatef(angle, 0.0, 1.0, 0.0); //rotate on the y axis 
    glRotatef(angle, 0.0, 0.0, 1.0); //rotate on the z axis 

    // bind texture 
    glActiveTexture(GL_TEXTURE0); 
    int loc = glGetUniformLocation(shader_program, "tex"); 
    glUniform1i(loc, 0); 
    glBindTexture(GL_TEXTURE_2D, tex_Box); 

    // bind normal texture 
    glActiveTexture(GL_TEXTURE1); 
    loc = glGetUniformLocation(shader_program, "tex_norm"); 
    glUniform1i(loc, 1); 
    glBindTexture(GL_TEXTURE_2D, tex_Norm); 

    // draw 
    glDrawArrays(GL_TRIANGLES, 0, 6*6); 

    // cleanup 
    glActiveTexture(GL_TEXTURE1); 
    glBindTexture(GL_TEXTURE_2D, 0); 
    glDisable(GL_TEXTURE_2D); 

    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, 0); 
    glDisable(GL_TEXTURE_2D); 

    glUseProgram(0); 
    SDL_GL_SwapBuffers(); 
} 

void clean_up() 
{ 
    glDeleteVertexArrays(1, &vao); 
    glDeleteBuffers(1, &vbo); 

    glDetachShader(shader_program, vertex_shader); 
    glDetachShader(shader_program, fragment_shader); 
    glDeleteShader(vertex_shader); 
    glDeleteShader(fragment_shader); 
    glDeleteProgram(shader_program); 

    SDL_QuitSubSystem(SDL_INIT_VIDEO); 
    glDeleteTextures(1, &tex_Box); 
    glDeleteTextures(1, &tex_Norm); 
    SDL_Quit(); 
} 

void dbpf(int t, const char * msg, ...) 
{ 
    va_start(m, msg); 
    if (t >= db_threashold) vfprintf(stderr, msg, m); 
    va_end(m); 
}