简体   繁体   English

如何不在OpenGL中使用着色器覆盖顶点颜色?

[英]How not to overwrite vertex colors using shaders in OpenGL?

For the past three hours I am trying to figure out how to draw two different triangles with different colours using shaders in OpenGL and still cannot figure it out. 在过去的三个小时中,我试图弄清楚如何使用OpenGL中的着色器绘制具有不同颜色的两个不同的三角形,但仍然无法弄清楚。 Here is my code: 这是我的代码:

void setShaders(void)
{

  vshader = loadShader("test.vert", GL_VERTEX_SHADER_ARB);
  fshader = loadShader("test.frag", GL_FRAGMENT_SHADER_ARB);
  vshader2 = loadShader("test2.vert", GL_VERTEX_SHADER_ARB);
  fshader2 = loadShader("test2.frag", GL_FRAGMENT_SHADER_ARB);

  shaderProg = glCreateProgramObjectARB();
  glAttachObjectARB(shaderProg, vshader);
  glAttachObjectARB(shaderProg, fshader);
  glLinkProgramARB(shaderProg);

  shaderProg2 = glCreateProgramObjectARB();
  glAttachObjectARB(shaderProg2, vshader2);
  glAttachObjectARB(shaderProg2, fshader2);
  glLinkProgramARB(shaderProg2);

}

void makeBuffers(void)
{
// smaller orange triangle
  glGenBuffers (1, &vbo);
  glBindBuffer (GL_ARRAY_BUFFER, vbo);
  glBufferData (GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);

  glGenVertexArrays (1, &vao);
  glBindVertexArray (vao);
  glEnableVertexAttribArray (0);
  glBindBuffer (GL_ARRAY_BUFFER, vbo);
  glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL);

// larger purple triangle
  glGenBuffers (1, &vbo2);
  glBindBuffer (GL_ARRAY_BUFFER, vbo2);
  glBufferData (GL_ARRAY_BUFFER, sizeof(points2), points2, GL_STATIC_DRAW);

  glGenVertexArrays (1, &vao2);
  glBindVertexArray (vao2);
  glEnableVertexAttribArray (0);
  glBindBuffer (GL_ARRAY_BUFFER, vbo2);
  glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL);

}

void window::displayCallback(void)
{
  Matrix4 m4;           // MT = UT * SpinMatrix
  m4 = cube.getMatrix();      //  make copy of the cube main matrix
  cube.get_spin().mult(m4);       //  mult 

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // clear color and depth buffers
  glMatrixMode(GL_MODELVIEW);
  glLoadMatrixd(cube.get_spin().getPointer());  // pass the pointer to new MT matrix 

  // draw smaller orange triangle
  glUseProgramObjectARB(shaderProg);

  glBindVertexArray(vao);
  glDrawArrays (GL_TRIANGLES, 0, 3);

  glDeleteObjectARB(shaderProg);

  // draw the larger purple triangle
  glUseProgramObjectARB(shaderProg2);

  glBindVertexArray(vao2);
  glDrawArrays (GL_TRIANGLES, 0, 3);

  glDeleteObjectARB(shaderProg2);

  glFlush();
  glutSwapBuffers();
}

shaders: 着色器:

test.vert and test2.vert are the same and are: test.vert和test2.vert相同,分别是:

#version 120

//varying vec3 vp; 

void main()
{
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

test.frag: test.frag:

#version 120

void main()
{
  gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0);
}

test2.frag: test2.frag:

#version 120

void main()
{
  gl_FragColor = vec4(0.5, 0.0, 0.5, 1.0);
}

But what I get is two triangles that are coloured purple. 但是我得到的是两个紫色的三角形。 What am I doing wrong that causes my smaller orange triangle is getting rewritten in purple colour? 我在做错什么导致我的较小的橙色三角形被改写成紫色?

You are deleting the shader programs after you use them in the displayCallback() method: displayCallback()方法中使用着色器程序后,将它们删除:

...
glDrawArrays (GL_TRIANGLES, 0, 3);
glDeleteObjectARB(shaderProg);

...
glDrawArrays (GL_TRIANGLES, 0, 3);
glDeleteObjectARB(shaderProg2);

If drawCallback() is called more than once, which you certainly need to expect since a window will often have to be redrawn multiple times, the shaders will be gone after the first time. 如果drawCallback()调用drawCallback() (您肯定会期望这样做,因为通常必须多次重绘窗口),因此着色器将在第一次使用后消失。 In fact, the second one will not be immediately deleted because it is the currently active program. 实际上,第二个程序不会被立即删除,因为它是当前活动的程序。 Which explains why it continues to be used for both triangles. 这就解释了为什么它继续用于两个三角形。

Shader programs are only deleted after glDelete*() is called on them, and they are not referenced as the active program. 仅在对它们着色器程序调用glDelete*()之后,它们才会被删除, 并且它们不会作为活动程序被引用。 So on your first glDelete*() call for shaderProg , that program is deleted once you make shaderProg2 active, because shaderProg is then not active anymore, which releases its last reference. 所以,你的第一个glDelete*()呼吁shaderProg ,一旦你作出这样的程序被删除shaderProg2活跃,因为shaderProg是那么不积极了,从而释放其最后一个引用。

You should not delete the shader programs until shutdown, or until you don't plan to use them anymore for rendering because eg you're creating new prgrams. 在关闭或不打算再使用着色器程序渲染之前,您不应该删除它们,因为例如,您正在创建新的程序。 So in your case, you can delete them when the application exits. 因此,根据您的情况,您可以在应用程序退出时将其删除。 At least that's often considered good style, even though it's not technically necessary. 至少在技术上没有必要的情况下,通常认为它是好的样式。 OpenGL resources will be cleaned up automatically when an application exits, similar to regular memory allocations. 退出常规应用程序时,将在应用程序退出时自动清除OpenGL资源。

BTW, if you are using at least OpenGL 2.0, all the calls for using shaders and programs are core functionality. 顺便说一句,如果您至少使用OpenGL 2.0,则所有使用着色器和程序的调用都是核心功能。 There's no need to use the ARB version calls. 无需使用ARB版本调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM