我如何在 SDL2 中显示 OpenGL 纹理
How do i display an OpenGL texture in SDL2
在 SDL2 window 中,我绘制了一个矩形,我打算在其上显示图像。我现在遇到的问题是 window 完全是黑色的。它既不显示彩色矩形,也不显示应该放在矩形上的图像。
#define SDL_MAIN_HANDLED
#include <GL\glew.h>
#include <GL\gl.h>
#include <SDL2\SDL.h>
#include "stb_image.h"
#include <cstdio>
const GLchar *vertexSource =
R"glsl(
#version 150 core
in vec2 position;
in vec3 color;
in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
Color = color;
Texcoord = texcoord;
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
const GLchar *fragmentSource =
R"glsl(
#version 150 core
in vec3 Color;
in vec2 Texcoord;
out vec4 outColor;
uniform sampler2D tex;
void main()
{
outColor = texture(tex, Texcoord) * vec4(Color, 1.0);
}
)glsl";
int main()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::puts("Could not initialize SDL2!");
exit(1);
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE);
SDL_Window *mainWindow = SDL_CreateWindow("Main Window",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600,
SDL_WINDOW_OPENGL);
if (nullptr == mainWindow)
{
std::puts("Could not create window!");
SDL_Quit();
exit(1);
}
if (!SDL_GL_CreateContext(mainWindow))
{
std::puts("Could not create context!");
SDL_Quit();
exit(1);
}
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::puts("Could not initialize GLEW!");
SDL_Quit();
exit(1);
}
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint ebo;
glGenBuffers(1, &ebo);
GLuint elements[] =
{ 0, 1, 2, 2, 3, 0 };
glBindBuffer(GL_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, 0);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, 0);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float),
0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float),
(void*) (2 * sizeof(GLfloat)));
GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float),
(void*) (5 * sizeof(GLfloat)));
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
int width, height, noOfChannels;
unsigned char *imageData = stbi_load("path",
&width, &height, &noOfChannels, 0);
if (imageData)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
}
else
{
std::puts("Could not load image");
SDL_Quit();
exit(1);
}
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_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
SDL_Event event;
bool running = true;
while (running)
{
while (SDL_PollEvent(&event) != 0)
{
if (event.type == SDL_QUIT)
{
running = false;
}
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
SDL_GL_SwapWindow(mainWindow);
}
glDeleteTextures(1, &texture);
glDeleteProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ebo);
glDeleteVertexArrays(1, &vao);
SDL_Quit();
return 0;
}
是不是主循环有什么地方没有正确显示图像?我的理解是,对于每个循环,我都应该清除屏幕,绘制形状,然后加载包含我的图像的后台缓冲区。
glDrawElements
is intended for use with an Index buffer (GL_ELEMENT_ARRAY_BUFFER
). You have accidentally specified 2 Vertex Buffers (GL_ARRAY_BUFFER
),但没有索引缓冲区:
glBindBuffer(GL_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
在 SDL2 window 中,我绘制了一个矩形,我打算在其上显示图像。我现在遇到的问题是 window 完全是黑色的。它既不显示彩色矩形,也不显示应该放在矩形上的图像。
#define SDL_MAIN_HANDLED
#include <GL\glew.h>
#include <GL\gl.h>
#include <SDL2\SDL.h>
#include "stb_image.h"
#include <cstdio>
const GLchar *vertexSource =
R"glsl(
#version 150 core
in vec2 position;
in vec3 color;
in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
Color = color;
Texcoord = texcoord;
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
const GLchar *fragmentSource =
R"glsl(
#version 150 core
in vec3 Color;
in vec2 Texcoord;
out vec4 outColor;
uniform sampler2D tex;
void main()
{
outColor = texture(tex, Texcoord) * vec4(Color, 1.0);
}
)glsl";
int main()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::puts("Could not initialize SDL2!");
exit(1);
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE);
SDL_Window *mainWindow = SDL_CreateWindow("Main Window",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600,
SDL_WINDOW_OPENGL);
if (nullptr == mainWindow)
{
std::puts("Could not create window!");
SDL_Quit();
exit(1);
}
if (!SDL_GL_CreateContext(mainWindow))
{
std::puts("Could not create context!");
SDL_Quit();
exit(1);
}
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::puts("Could not initialize GLEW!");
SDL_Quit();
exit(1);
}
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint ebo;
glGenBuffers(1, &ebo);
GLuint elements[] =
{ 0, 1, 2, 2, 3, 0 };
glBindBuffer(GL_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, 0);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, 0);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float),
0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float),
(void*) (2 * sizeof(GLfloat)));
GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float),
(void*) (5 * sizeof(GLfloat)));
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
int width, height, noOfChannels;
unsigned char *imageData = stbi_load("path",
&width, &height, &noOfChannels, 0);
if (imageData)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
}
else
{
std::puts("Could not load image");
SDL_Quit();
exit(1);
}
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_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
SDL_Event event;
bool running = true;
while (running)
{
while (SDL_PollEvent(&event) != 0)
{
if (event.type == SDL_QUIT)
{
running = false;
}
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
SDL_GL_SwapWindow(mainWindow);
}
glDeleteTextures(1, &texture);
glDeleteProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ebo);
glDeleteVertexArrays(1, &vao);
SDL_Quit();
return 0;
}
是不是主循环有什么地方没有正确显示图像?我的理解是,对于每个循环,我都应该清除屏幕,绘制形状,然后加载包含我的图像的后台缓冲区。
glDrawElements
is intended for use with an Index buffer (GL_ELEMENT_ARRAY_BUFFER
). You have accidentally specified 2 Vertex Buffers (GL_ARRAY_BUFFER
),但没有索引缓冲区:
glBindBuffer(GL_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);