如何在渲染之间更改片段着色器颜色?
Posted
技术标签:
【中文标题】如何在渲染之间更改片段着色器颜色?【英文标题】:How to change fragment shader color between renders? 【发布时间】:2014-04-15 01:01:44 【问题描述】:我正在努力编写这个简单的船场景。这是一个家庭作业问题,但我真的很难过。我有两个我上传的模型。一个是一个立方体,它有一个片段着色器来将自己染成蓝色。第二个是一艘船,它有一个片段着色器将自己着色为白色。当我使用两个不同的着色器时,船模型是不可见的。经过许多挣扎和搜索
我很困惑,所以我正在尝试 B 计划,该计划是找到一种在渲染两个对象之间更改片段着色器颜色的方法,但我不知道该怎么做。
void render()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//BOAT START
//Rocks the ship, simulating ocean rocking
if(shiprocker < 5000)
shiprocker++;
theta += 0.00002f;
if(shiprocker ==15000)
shiprocker = -5000;
if(shiprocker > 4999)
shiprocker++;
theta -= 0.00002f;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
boat_model->mR = glm::rotate(
glm::mat4( 1.0f ),
glm::degrees( theta ),
glm::vec3(0.0f, 0.0f, 1.0f)
);
glm::mat4 mtx_trans = glm::translate(
glm::mat4(1.0f),
glm::vec3( 0.0f, 0.0f, -15.0f )
);
boat_model->mM = mtx_trans * boat_model->mR;
boat_model->render();
//BOAT END
//OCEAN CUBE START
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glm::mat4 mtx_trans_cube = glm::translate(
glm::mat4( 1.0f ),
glm::vec3( -20.0f, -50.0f, -50.0f )
);
plane_model->mM = glm::scale(
mtx_trans_cube,
glm::vec3( 10.0f, 10.0f, 10.0f )
);
//gl_FragColor = (0.0f, 0.0f, 1.0f , 1.0f); wont compile
//glColor3f(0.0f, 0.0f, 1.0f); changes nothing
camera->set_uniform_view_perspective( plane_model->shader->program_ID );
plane_model->render();
//OCEAN CUBE END
glutSwapBuffers();
int main (int argc, char** argv)
// Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_MULTISAMPLE | GLUT_RGB);
//WINDOW SETTINGS
glutInitWindowSize(1000, 1000);
glutCreateWindow("SailBoat");
//PASSIVE FUNCS
glutReshapeFunc(change_viewport);
glutDisplayFunc(render);
glutIdleFunc( animate );
//ERROR CHECK
if (GLEW_OK != glewInit())
exit(1);
//Clear color used for sky tones.
glClearColor(0.529f, 0.807f, .98f, 1.0f);
glEnable (GL_DEPTH_TEST);
glEnable (GL_MULTISAMPLE);
Shader* boatShader = new Shader( VERTEX_SHADER, BOAT_FRAGMENT_SHADER );
Shader* cubeShader = new Shader( VERTEX_SHADER, CUBE_FRAGMENT_SHADER );
//BOAT
boat_model = new Model(boatShader);
load_model(boat_model ,MODEL_BOAT_FILENAME);
boat_model->upload_2_server();
//OCEAN CUBE
plane_model = new Model( boatShader );
load_model(plane_model ,MODEL_PLANE_FILENAME);
plane_model->upload_2_server();
// Set up the camera
theta = 0.0f;
shiprocker = 0;
camera = new FPSCamera(60.0f, 1.0f, 1.0f, 10000.0f, true);
glutMainLoop();
return 0;
片段着色器
#version 150
in vec4 color;
out vec4 fColor;
void main ()
fColor = vec4(1.0, 1.0, 1.0, 0.5);
【问题讨论】:
你试过使用 GLSL 统一变量吗? 在您的Model.render
函数中,您是在调用Shader->use
还是类似的名称?
【参考方案1】:
您可以在 GLSL 中使用统一变量在渲染调用之间传递值。像这样设置你的片段着色器:
#version 150
in vec4 color;
out vec4 fColor;
uniform vec3 boatColor;
void main ()
fColor = vec4(boatColor, 0.5);
在你的 C++ 代码中:
glUseProgram(program); // Where program is your shader program
GLint uniform = glGetUniformLocation(program, "boatColor"); // since boatColor is what we called the uniform variable in our fragment shader
glUniform3f(uniform, 1.0f, 0.0f, 0.0f); // Set the boatColor variable to be a solid red
// Render your first boat
glUniform3f(uniform, 0.0f, 0.0f, 1.0f); // Set the second boat to be a solid blue
// Render your second boat
glUseProgram(0);
这应该很好用。如果这里的其他人有更好的方法,请告诉我;我对 GLSL 比较陌生。
【讨论】:
这看起来是一个非常好的方法,Chemo 先生。如果您有很多相对较小的对象,并且关心尽可能好的性能,您还可以考虑使用属性而不是制服。它稍微复杂一些,因为它们首先进入顶点着色器,然后需要传递给片段着色器。但是根据平台和驱动程序的效率,更新制服的成本可能适中,而更新属性可能更有效。不过,您可能希望对其进行基准测试。 感谢您的帮助。我现在一切都在运行。我在 c++ 代码和着色器之间进行通信时遇到了很多麻烦,但你帮了我很多! @JellyJay 很高兴为您提供帮助!在这种情况下,请接受我的回答。 :)以上是关于如何在渲染之间更改片段着色器颜色?的主要内容,如果未能解决你的问题,请参考以下文章