所以我最近一直在学习一些 openGL。我最初一直在使用 SDL 库在屏幕上打印图像,但我认为有兴趣尝试使用 openGL 实现类似的东西,因此也能够将着色器应用于我的图像以获得整洁的效果,例如灯光效果和夜晚/日循环等。我现在正在做的只是加载一个纹理,然后将该纹理应用于具有相同大小的纹理的四边形。这很好用。
现在我想应用一些着色器。这是我可以应用于我的纹理四边形之一的顶点和片段着色器的示例:
in vec2 LVertexPos2D;
void main()
{
gl_Position = vec4( LVertexPos2D.x, LVertexPos2D.y, 0, 1);
}
什么都不做,然后是我的片段着色器:
out vec4 LFragment;
void main()
{
LFragment = vec4(1.0, 1.0, 1.0, 1.0);
}
这显然只是将我正在应用它的纹理变成了一个白色 block ,这并不是我想要的。我需要以某种方式检索当前纹素数据,以便我可以修改它而不是简单地更改它。
我读到对 texture2D 的函数调用应该返回当前像素数据的 vec4,但我还没有让它工作。 (很难找到对函数输入及其工作原理的很好解释)。此外,据推测 texture2D 已被弃用,但我也无法使其替代品 (texture()) 正常工作。任何朝着正确方向的插入将不胜感激!
编辑:我将提供更多关于我如何做事的信息,这是加载我的纹理的函数:
texture makeTexture(std::string fileLocation)
{
texture tempTexture;
SDL_Surface *mySurface = IMG_Load(fileLocation.c_str());
if (mySurface == NULL)
{
std::cout << "Error in loading image at: " << fileLocation << std::endl;
return tempTexture;
}
GLuint myTexture;
glGenTextures(1, &myTexture);
glBindTexture(GL_TEXTURE_2D, myTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mySurface->w, mySurface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mySurface->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
SDL_FreeSurface(mySurface);
tempTexture.texture_id = myTexture;
tempTexture.h = mySurface->h;
tempTexture.w = mySurface->w;
return tempTexture;
}
这是我的纹理结构:
struct texture
{
int w;
int h;
GLuint texture_id;
};
此函数将任何纹理绘制到给定的 x 和 y 坐标:
void draw(int y, int x, texture &tempTexture)
{
glBindTexture(GL_TEXTURE_2D, tempTexture.texture_id);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(-1 + ((float)(x) / SCREEN_WIDTH) * 2, 1 - ((float)(y + tempTexture.h) / SCREEN_HEIGHT) * 2); //Bottom left
glTexCoord2f(1, 1);
glVertex2f(-1 + ((float)(x + tempTexture.w)/SCREEN_WIDTH)*2, 1 - ((float)(y + tempTexture.h) / SCREEN_HEIGHT) * 2); //Bottom right?
glTexCoord2f(1, 0);
glVertex2f(-1 + ((float)(x + tempTexture.w) / SCREEN_WIDTH) * 2, 1.0 - ((float)y / SCREEN_HEIGHT) * 2); //top right
glTexCoord2f(0, 0);
glVertex2f(-1 + ((float)(x) / SCREEN_WIDTH) * 2, 1.0 - ((float)y / SCREEN_HEIGHT) * 2); //Top left (notification: Coordinates are (x,y), not (y,x).
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}
然后在我的主要渲染函数中,我正在做:
draw(0, 0, myTexture);
glUseProgram(gProgramID);
glUniform1i(baseImageLoc, myTexture2.texture_id);
draw(100, 100, myTexture2);
glUseProgram(NULL);
其中 myTexture 只是一片草地,而 myTexture2 是一个玩家角色,我想对其应用一些着色技巧。 gPriogramID 是一个加载了我前面提到的两个着色器的程序。
最佳答案
为了在着色器中访问纹理数据,您必须执行以下操作:
- 首先,您需要将纹理
glBind
到特定的纹理单元(使用glActiveTexture
更改事件纹理单元。 - 将纹理单元索引作为统一采样器传递给着色器。
像下面这样访问着色器中的纹理。
//tex 保存要使用的纹理单元的值(不是纹理) 均匀采样器 2D tex;
无效主() { vec4 颜色 = 纹理(tex,texCoord); LFragment = 颜色;
您还需要将 texCoords 作为 in
顶点属性传递给着色器。
关于c++ - openGL 片段着色器和原始纹素数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25260396/