gpt4 book ai didi

c - 使用顶点缓冲区和纹理缓冲区的 OpenGL C++ 顺序

转载 作者:行者123 更新时间:2023-11-30 15:32:35 24 4
gpt4 key购买 nike

我在将纹理加载到三角形 strip 上时遇到问题。我正在关注Anton Gerdelan's tutorial ,在我的主程序失败后,我回到了基础知识,只是尝试制作一个简单的正方形并在其上放置他的纹理(骷髅和交叉骨)。

我完全复制并粘贴了他的 "Hello Triangle" 中的代码页面,它有效,但是一旦尝试适应上面纹理教程中的代码(并将三角形更改为正方形),我得到的只是一个没有纹理的大白色正方形。

我已经使用 glGetShaderiv() 检查了着色器的状态,它们返回了正值,我检查了加载的图像以查看像素数据是否合理,所以我相信我的错误在于声明我的 VBO 或顺序/我在其中使用它们的参数。

这是我复制的完整代码,它可以在 Visual Studio 2013 中正常编译,但输出不是预期的结果。

我正在使用 GLEW 和 GLFW 的静态库以及 STBI 图像 header

#include <GL/glew.h> // include GLEW and new version of GL on Windows
#include <GL/glfw3.h> // GLFW helper library
#include <stdio.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>

const char* vertex_shader =
"#version 400\n"
"in vec3 vp;"
"layout (location=1) in vec2 vt; // per-vertex texture co-ords"
"out vec2 texture_coordinates; "
"void main () {"
" gl_Position = vec4 (vp, 1.0);"
" texture_coordinates = vt; "
"}";

const char* fragment_shader =
"#version 400\n"
"in vec2 texture_coordinates;"
"uniform sampler2D basic_texture;"
"out vec4 frag_colour;"
"void main () {"
"vec4 texel = texture(basic_texture, texture_coordinates);"
"frag_colour = texel; "
"}";

float points[] = {
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f

};

float texcoords[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0
};

GLFWwindow* window;
unsigned int vt_vbo;
unsigned int tex = 0;
GLuint vao = 0;
GLuint vbo = 0;
GLuint shader_programme;

void initializeGL(){
// start GL context and O/S window using the GLFW helper library
if (!glfwInit()) {
printf("ERROR: could not start GLFW3\n");
return;
}

window = glfwCreateWindow(640, 480, "Texture Test", NULL, NULL);
if (!window) {
printf("ERROR: could not open window with GLFW3\n");
glfwTerminate();
return;
}
glfwMakeContextCurrent(window);

// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();

// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);

// tell GL to only draw onto a pixel if the shape is closer to the viewer
glEnable(GL_DEPTH_TEST); // enable depth-testing
glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
}

void startShaders(){

GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);

shader_programme = glCreateProgram();
glAttachShader(shader_programme, fs);
glAttachShader(shader_programme, vs);
glLinkProgram(shader_programme);
GLint vsstat;
glGetShaderiv(vs, GL_COMPILE_STATUS, &vsstat);
GLint fsstat;
glGetShaderiv(fs, GL_COMPILE_STATUS, &fsstat);
printf("%i\n%i\n", vsstat, fsstat);
}

void loadImage(){
int x, y, n;
int force_channels = 4;
unsigned char* image_data = stbi_load("skulluvmap.png", &x, &y, &n, force_channels);
if (!image_data) {
printf("ERROR: could not load %s\n", "skulluvmap.png");
}

int width_in_bytes = x * 4;
unsigned char *top = NULL;
unsigned char *bottom = NULL;
unsigned char temp = 0;
int half_height = y / 2;


for (int row = 0; row < half_height; row++) {
top = image_data + row * width_in_bytes;
bottom = image_data + (y - row - 1) * width_in_bytes;
for (int col = 0; col < width_in_bytes; col++) {
temp = *top;
*top = *bottom;
*bottom = temp;
top++;
bottom++;
}
}
printf("first 4 bytes are: %i %i %i %i\n",
image_data[0], image_data[1], image_data[2], image_data[3]
);
glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}

void generateBuffers(){
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), points, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0); // don't forget this!

glGenBuffers(1, &vt_vbo);
glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), texcoords, GL_STATIC_DRAW);

glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1); // don't forget this!
}

void mainLoop(){
while (!glfwWindowShouldClose(window)) {
// wipe the drawing surface clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
int tex_loc = glGetUniformLocation(shader_programme, "basic_texture");
glUseProgram(shader_programme);
glUniform1i(tex_loc, 0); // use active texture 0
// draw points 0-4 from the currently bound VAO with current in-use shader
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// update other events like input handling
glfwPollEvents();
// put the stuff we've been drawing onto the display
glfwSwapBuffers(window);
}
}

int main() {

initializeGL();
startShaders();
loadImage();
generateBuffers();
mainLoop();

// close GL context and any other GLFW resources
glfwTerminate();
return 0;
}

最佳答案

您滥用了第二个缓冲区,它应该是带有 texcoords 的缓冲区。所以你真正想要实现的是每个顶点都有一对纹理坐标。这意味着 texcoords 数组实际上应该存储 4 对,因为点数组中有 4 个三元组。这是第一个修复。您可能希望它看起来像:

float texcoords[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0, 0.0,
1.0, 1.0,
};

然后在generateBuffers中,您的vt_vbo是错误的。数据应该这样传递:

glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), texcoords, GL_STATIC_DRAW);

因为您只想在那里传递 8 个值。每个顶点 2 个纹理坐标。

编辑:

然而,这并不能完全解释为什么你的纹理根本不出现。我主要认为您的 texcoords 指针可能有问题,但事实似乎并非如此。

关于c - 使用顶点缓冲区和纹理缓冲区的 OpenGL C++ 顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24141595/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com