Home > Enterprise >  OpenGL: glColor3f() and glVertex3f() with shader
OpenGL: glColor3f() and glVertex3f() with shader

Time:12-19

Can I use glColor3f(), glVertex3f() or other API functions with shader? I wrote a shader for draw a colorful cube and it works fine. My vertex shader and fragment shader look like this

#vertext shader
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;
out vec4 vertexColor;
void main()
{
    gl_Position = proj * view * model * vec4(aPos.x, aPos.y, aPos.z, 1.0);
    vertexColor = vec4(aColor, 1.0);
};

#fragment shader
#version 330 core
in vec4 vertexColor;
out vec4 FragColor;
void main(){
    FragColor = vertexColor;
};

Noe, I try to use gl functions along with my colorful cube. Let's say I have some draw code like this.

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -1, 0, 0, 0, 0, 1, 0);
glColor3f(1.0, 0.0, 0.0);
glLineWidth(3);
glBegin(GL_LINES);
glVertex3f(-1, -1, 0);
glVertex3f(1, 1, 0);

Since I used glUseProgram() to use my own shader. The above gl functions doesn't seems to work as expect (coordinates and color are both wrong). How does function like glVertex3f() pass vertex to shader? And how do the shaders should look like when using gl function to draw?

CodePudding user response:

Can I use glColor3f(), glVertex3f() or other API functions with shader?

Yes you can.

However, you need to use a Compatibility profile OpenGL Context and you are limited to a GLSL 1.20 vertex shader and the Vertex Shader Built-In Attributes (e.g. gl_Vertex, gl_Color). You can combine a GLSL 1.20 vertex shader with your fragment shader. The matrices in the fixed function matrix stack can be accessed with Built-In Uniforms like gl_ModelViewProjectionMatrix.
All attributes and uniforms are specified in detail in the OpenGL Shading Language 1.20 Specification.

A suitable vertex shader can look like this:

#version 120

varying vec4 vertexColor;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    vertexColor = gl_Color;
};
#version 330

in vec4 vertexColor;
out vec4 FragColor;

void main(){
    FragColor = vertexColor;
};

CodePudding user response:

The glBegin()/glEnd() directives are used in compatibility profile of OpenGL as opposed to core profile which is more modern. However you are compiling your shaders in core profile using the line #version 330 core.

Even if the shaders are not compiled in the core profile, I don't think they'll work since I believe you can't pass vertex attributes with location indices (aPos, aColor) using glVertex3f.

I would recommend using the core Opengl for render calls. That means you should not use you glBegin()...glEnd() and pass vertex coordinates in every render cycle. Instead, the cube coordinates to GPU before-hand and let your shaders access those values:

  1. Create VertexBuffer objects using glGenBuffers().
  2. Store your vertex data in the buffer using glBufferData().
  3. Extract the aPos and aColor attributes from the buffer and assign them indices of 0 and 1 respectively using glVertexAttribPointer().

This should work and no changes to your shader code would be necessary.

EDIT:

For rendering in compatibility profile, the data provided within glBegin/glEnd is ran through a default shader pipeline. You can't customize the pipeline using explicit shader code (like you did now), but you can modify some basic things in the pipeline (such as color, phong lighting, texture). So if you want to get the results your shader code represents, you need to do something like this:

glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(-1.0f,-0.25f,0.0f); //First vertex
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-0.5f,-0.25f,0.0f); // Second vertex
...
glEnd();

This way of sending full object details during render call is called Immediate mode. For adding lighting, you need glEnable(GL_LIGHTING), add normal info for each vertex and a bunch of other stuff.

If you use core profile, you can define your own shaders but you can't use Immediate mode during the render calls. You need to pass the vertex data before your rendering loop. Basically glBegin,glEnd,'glVertex3f' are not supported in core profile and you need to use the 3 points above to store the data in your graphics device before your render anything (which is done using glDrawArrays()). This tutorial provides a good introduction to these concepts and can help you draw the cube you want using core profile.

  • Related