OpenGL에서 VBO에 텍스처를 맵핑하는 문제
문제
OpenGL로 지오메트리에 맵핑 할 텍스처를 얻는 데 어려움이 있습니다. 사실 나는 잘 작동했던 색 보간을 깨뜨린 것 같습니다. C99에서 SDL, GLEE 및 토양을 사용하는 테스트 케이스를 만들었습니다.
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <SDL/SDL.h>
#include <GL/GLee.h>
#include <SOIL/SOIL.h>
static const char *vertex_source = " \
uniform mat4 projection; \
uniform mat4 view_model; \
\
attribute vec2 vertex; \
attribute vec2 texcoord; \
attribute vec4 colour; \
\
varying vec2 _texcoord; \
\
void main() \
{ \
gl_Position = gl_ModelViewProjectionMatrix * vec4(vertex, 0, 1); \
_texcoord = texcoord; \
gl_FrontColor = colour; \
} ";
static const char *fragment_source = " \
uniform sampler2D sampler0; \
\
varying vec2 _texcoord; \
\
void main() \
{ \
gl_FragColor = texture2D(sampler0, _texcoord) * 0.01 + gl_Color; \
} ";
typedef struct
{
GLfloat position[2];
GLfloat texcoord[2];
GLubyte colour[4];
} Vertex;
static Vertex verts[] = {
{
.position = { 1, 1 },
.texcoord = { 1, 1 },
.colour = { 255, 0, 0, 255 },
},
{
.position = { -1, 1 },
.texcoord = { 0, 1 },
.colour = { 0, 255, 0, 255 },
},
{
.position = { -1, -1 },
.texcoord = { 0, 0 },
.colour = { 0, 0, 255, 255 },
},
{
.position = { 1, -1 },
.texcoord = { 1, 0 },
.colour = { 255, 255, 0, 255 },
},
};
static GLuint vertex, fragment, program, vbo, texture;
static GLint sampler_loc, vertex_loc, texcoord_loc, colour_loc;
static void init()
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_SetVideoMode(800, 800, 0, SDL_OPENGL);
glClearColor(1, 0, 0, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-1, 1, -1, 1, -1, 1);
/* Shaders */
vertex = glCreateShader(GL_VERTEX_SHADER);
assert(vertex != 0);
fragment = glCreateShader(GL_FRAGMENT_SHADER);
assert(fragment != 0);
GLint length = strlen(vertex_source);
glShaderSource(vertex, 1, &vertex_source, &length);
length = strlen(fragment_source);
glShaderSource(fragment, 1, &fragment_source, &length);
glCompileShader(vertex);
glCompileShader(fragment);
program = glCreateProgram();
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
sampler_loc = glGetUniformLocation(program, "sampler0");
vertex_loc = glGetAttribLocation(program, "vertex");
texcoord_loc = glGetAttribLocation(program, "texcoord");
colour_loc = glGetAttribLocation(program, "colour");
/* VBO */
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
/* Texture */
texture = SOIL_load_OGL_texture("test.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
assert(texture != 0);
}
static void draw()
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(sampler_loc, 0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glScalef(.5, .5, .5);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, position));
glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, texcoord));
glVertexAttribPointer(colour_loc, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), offsetof(Vertex, colour));
glDrawArrays(GL_QUADS, 0, 4);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glPopMatrix();
glUseProgram(0);
}
static void shutdown()
{
SDL_Quit();
}
int main()
{
init();
atexit(shutdown);
while(true)
{
static SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
exit(0);
break;
default:
break;
}
}
draw();
SDL_GL_SwapBuffers();
if(glGetError() != GL_NO_ERROR)
{
printf("Error\n");
exit(1);
}
}
return 0;
}
렌더링하는 유일한 것은 glclearcolor 위에있는 평범한 파란색 사각형입니다.
도움이 주셔서 감사합니다.
답변 해 주셔서 감사합니다. 완전성을 위해 고정 코드를 첨부했습니다.
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <SDL/SDL.h>
#include <GL/GLee.h>
#include <SOIL/SOIL.h>
static const char *vertex_source = " \
uniform mat4 projection; \
uniform mat4 view_model; \
\
attribute vec2 vertex; \
attribute vec2 texcoord; \
attribute vec4 colour; \
\
varying vec2 _texcoord; \
\
void main() \
{ \
gl_Position = gl_ModelViewProjectionMatrix * vec4(vertex, 0, 1); \
_texcoord = texcoord; \
gl_FrontColor = colour; \
} ";
static const char *fragment_source = " \
uniform sampler2D sampler0; \
\
varying vec2 _texcoord; \
\
void main() \
{ \
gl_FragColor = texture2D(sampler0, _texcoord) + gl_Color; \
} ";
typedef struct
{
GLfloat position[2];
GLfloat texcoord[2];
GLubyte colour[4];
} Vertex;
static Vertex verts[] = {
{
.position = { 1, 1 },
.texcoord = { 1, 1 },
.colour = { 255, 0, 0, 255 },
},
{
.position = { -1, 1 },
.texcoord = { 0, 1 },
.colour = { 0, 255, 0, 255 },
},
{
.position = { -1, -1 },
.texcoord = { 0, 0 },
.colour = { 0, 0, 255, 255 },
},
{
.position = { 1, -1 },
.texcoord = { 1, 0 },
.colour = { 255, 255, 0, 255 },
},
};
static GLuint vertex, fragment, program, vbo, texture;
static GLint sampler_loc, vertex_loc, texcoord_loc, colour_loc;
static void init()
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_SetVideoMode(800, 800, 0, SDL_OPENGL);
glClearColor(1, 0, 0, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-1, 1, -1, 1, -1, 1);
/* Shaders */
vertex = glCreateShader(GL_VERTEX_SHADER);
assert(vertex != 0);
fragment = glCreateShader(GL_FRAGMENT_SHADER);
assert(fragment != 0);
GLint length = strlen(vertex_source);
glShaderSource(vertex, 1, &vertex_source, &length);
length = strlen(fragment_source);
glShaderSource(fragment, 1, &fragment_source, &length);
glCompileShader(vertex);
glCompileShader(fragment);
program = glCreateProgram();
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
sampler_loc = glGetUniformLocation(program, "sampler0");
vertex_loc = glGetAttribLocation(program, "vertex");
texcoord_loc = glGetAttribLocation(program, "texcoord");
colour_loc = glGetAttribLocation(program, "colour");
glUseProgram(program);
glUniform1i(sampler_loc, 0);
glUseProgram(0);
/* VBO */
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts[0], GL_STATIC_DRAW);
glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, position));
glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, texcoord));
glVertexAttribPointer(colour_loc, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), offsetof(Vertex, colour));
glBindBuffer(GL_ARRAY_BUFFER, 0);
/* Texture */
texture = SOIL_load_OGL_texture("test.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
assert(texture != 0);
}
static void draw()
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glScalef(.5, .5, .5);
glEnableVertexAttribArray(vertex_loc);
glEnableVertexAttribArray(texcoord_loc);
glEnableVertexAttribArray(colour_loc);
glDrawArrays(GL_QUADS, 0, 4);
glDisableVertexAttribArray(vertex_loc);
glDisableVertexAttribArray(texcoord_loc);
glDisableVertexAttribArray(colour_loc);
glBindTexture(GL_TEXTURE_2D, 0);
glPopMatrix();
glUseProgram(0);
}
static void shutdown()
{
SDL_Quit();
}
int main()
{
init();
atexit(shutdown);
while(true)
{
static SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
exit(0);
break;
default:
break;
}
}
draw();
SDL_GL_SwapBuffers();
if(glGetError() != GL_NO_ERROR)
{
printf("Error\n");
exit(1);
}
}
return 0;
}
해결책
Vertex Attrib 어레이를 올바르게 활성화하지 않습니다.
- 당신은 당신이 사용하는 것도 아닐 수도있는 0을 활성화합니다 (실제로는 아마도 아마
vertex_loc
,하지만 당신은 그것에 의존해서는 안됩니다) - 다른 두 배열을 무시합니다
다음을 시도하십시오.
glEnableVertexAttribArray(vertex_loc);
glEnableVertexAttribArray(texcoord_loc);
glEnableVertexAttribArray(colour_loc);
추가 할 편집 : 다른 세부 사항을 지적 할 수도 있습니다.
샘플러 위치를 한 번만 설정했습니다. 설정은 드라이버에서 추가 작업을 강요하는 경향이 있으며 매번 동일한 텍스처 유닛으로 만 설정하므로 시작시에도 할 수도 있습니다.
당신이 부르는 곳
glBindBuffer(GL_ARRAY_BUFFER, 0)
틀리지는 않지만 vertexattribpointer 호출 직후에 넣었습니다. 현재 바인딩 버퍼는 실제로 해당 통화에 대한 추가 논쟁 일뿐입니다. 그리고 GlDrawArrays 호출 자체에 영향을 미치지 않습니다.
다른 팁
셰이더에는 하위 표현이 포함되어 있습니다
texture2D(sampler0, _texcoord) * 0.01
대부분의 디스플레이에서 당신의 질감이 본질적으로 보이지 않게 만드는 것은 무엇입니까?
afaik vbo의 텍스처를 바인딩하기 전에 glclientactiveTexture ()를 사용해야합니다.
제휴하지 않습니다 StackOverflow