[英]Texture sampling coordinates seemingly scaled by factor of 2 in OpenGL/SDL2 tutorial
我編寫了一個簡單的 OpenGL 程序來采樣 256x256 PNG 紋理並將其渲染到 window 中的矩形上。 為此,我嚴重依賴教程。 當我幾乎直接按照教程進行操作時(進行最小的更改以便將 SDL2 用於 [x]),紋理沒有正確渲染,並且似乎以某種方式縮小了 2 倍。這是源代碼的第一個版本,以及結果的屏幕截圖:
// Link statically with GLEW
#define GLEW_STATIC
// Headers
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_opengl.h>
// Shader sources
const GLchar* vertexSource = R"glsl(
#version 150 core
in vec2 position;
in vec2 color;
out vec2 Color;
void main()
{
Color = color;
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
const GLchar* fragmentSource = R"glsl(
#version 150 core
in vec2 Color;
out vec4 outColor;
uniform sampler2D tex;
void main()
{
outColor = texture(tex,Color);
}
)glsl";
int main()
{
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_Window* window = SDL_CreateWindow("OpenGL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_GLContext context = SDL_GL_CreateContext(window);
glViewport(0, 0, 800, 600);
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {
// x y u v
-0.5f, 0.5f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 1.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 0.0f, 1.0f // Bottom-left
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Create an element array
GLuint ebo;
glGenBuffers(1, &ebo);
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
SDL_Surface* surface = IMG_Load("../textures/16x16-sb-ascii.png");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
SDL_FreeSurface(surface);
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);
bool running = true;
while (running)
{
SDL_Event windowEvent;
while (SDL_PollEvent(&windowEvent))
{
switch (windowEvent.type)
{
case SDL_QUIT:
running = false;
break;
}
}
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw a rectangle from the 2 triangles using 6 indices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// Swap buffers
SDL_GL_SwapWindow(window);
}
glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &ebo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
SDL_Quit();
return 0;
}
作為參考,這里是實際的紋理文件:
如您所見,矩形的不同象限中的紋理似乎已經翻了兩番,下面的兩個副本莫名其妙地被徹底破壞了。
正如人們所預料的那樣,將所有紋理坐標歸一化為 0.5 會在預期比例下生成一個紋理副本,盡管仍然可以看到許多奇怪的黃色/藍色偽影,邊緣周圍還有一些非常細微的噪聲偽影:
GLfloat vertices[] = {
// x y u v
-0.5f, 0.5f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 0.5f, 0.0f, // Top-right
0.5f, -0.5f, 0.5f, 0.5f, // Bottom-right
-0.5f, -0.5f, 0.0f, 0.5f // Bottom-left
};
我在預裝了 Ubuntu 18.04.4 LTS 的戴爾筆記本電腦上執行此操作。 我的顯卡是 Intel UHD Graphics 630 (Coffeelake 3x8 GT2)。
運行 glxinfo | grep“OpenGL 版本”給出以下結果:OpenGL 版本字符串:3.0 Mesa 19.2.8。
任何有關縮放或藍色/黃色偽影的幫助將不勝感激。 謝謝!
生成的紋理圖像是亮度/alpha 圖像,只有一個顏色通道和一個 alpha 通道。 因此,當您通過glTexImage2D
指定二維紋理圖像時,您必須使用格式GL_RG
:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG, surface->w, surface->h, 0,
GL_RG, GL_UNSIGNED_BYTE, surface->pixels);
設置Swizzle 蒙版以從紅色通道讀取綠色和藍色以及從綠色通道讀取 alpha 值:
GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_GREEN};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
或者在片段着色器中進行紋理查找時使用Swizzling獲取紅色通道和 alpha 通道:
#version 150 core
in vec2 Color;
out vec4 outColor;
uniform sampler2D tex;
void main()
{
outColor = texture(tex,Color).rrrg;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.