c++ - OpenGL shader linking -
after following set of opengl tutorials great didn't let me understand basics, i'm trying basic opengl coding c++. program supposed read vertex , fragment shader , draw triangle.
i error when linking shaders (i suspect error can tracked down compiling of shader though). know shaders read program, changes them doesn't affect error. running:
glgetprogramiv(shaderprogram, gl_link_status, &success);
i receive error: "link called without attached shader object". programs builds, , triangle shows, not affected shaders.
update
i no longer above error after fixing mistake. complain after glcompileshader():
"error: 0:3 'location' : syntax error parse error"
so imagine has shader files (will add them below). shader files taken tutorial, assumed work.
shader files:
vertex shader:
#version 330 layout (location = 0) in vec3 position; void main() { gl_position = vec4(0.5*position.x, 0.5*position.y, position.z, 1.0); }
fragment shader:
#version 330 out vec4 fragcolor; void main() { fragcolor = vec4(1.0, 0.0, 0.0, 1.0); }
in main function run:
compileshader();
attach shaders:
static void addshader(gluint shaderprogram, glenum shadertype, std::string filepath){ //create shader object gluint shaderobj = glcreateshader(shadertype); //error if no shader if (shaderobj == 0){ fprintf(stderr, "error creating shader type %d\n", shadertype); exit(0); } //"specify source code" //readshaderfile returns shader file string std::string shaderfile = readshaderfile(filepath); const char* shaderfilepointer = shaderfile.c_str(); glint shaderfilelength[1]; shaderfilelength[0] = strlen(shaderfilepointer); glshadersource(shaderobj, 1, &shaderfilepointer, shaderfilelength); //compile shader glcompileshader(shaderobj); //check if compile successful glint success; glgetshaderiv(shaderobj, gl_compile_status, &success); if (!success){ glchar infolog[1024]; glgetshaderinfolog(shaderobj, sizeof(infolog), null, infolog); fprintf(stderr, "error compiling shader type %d: '%s'\n", shadertype, infolog); exit(1); } glattachshader(shaderprogram, shaderobj); }
and here functions used:
static void compileshaders(){ //create program gluint shaderprogram = glcreateprogram(); //check error if (shaderprogram == 0){ fprintf(stderr, "error creating shader program!\n"); exit(1); } //attach compiled shaders std::string vertexshaderfilepath = "shaders/colshading.vert"; std::string fragshaderfilepath = "shaders/colshading.frag"; addshader(shaderprogram, gl_vertex_shader, vertexshaderfilepath); addshader(shaderprogram, gl_fragment_shader, fragshaderfilepath); glint success = 0; glchar errorlog[1024] = { 0 }; //link shader program gllinkprogram(shaderprogram); //check link error glgetprogramiv(shaderprogram, gl_link_status, &success); if (success == 0) { glgetprograminfolog(shaderprogram, sizeof(errorlog), null, errorlog); fprintf(stderr, "error linking shader program: '%s'\n", errorlog); } //use linked shader program gluseprogram(shaderprogram); }
i doubt more of code needed find problem here, let me know. lot in advance!
solution
the first answer below did trick. removed:
layout (location = 0)
from vertex shader , added:
glbindattriblocation(shaderprogram, 0, "position");
before linking.
it seems either hardware or driver doesn't support explicit shader location syntax, require opengl/glsl > 3.3.
to solve this, if samgak's answer doesn't help, still have 2 options:
- explicitly set locations before linking shader:
this done glbindattriblocation
function, , means same have in shader. example:
addshader(shaderprogram, gl_vertex_shader, vertexshaderfilepath); addshader(shaderprogram, gl_fragment_shader, fragshaderfilepath); //... //define location of attributes glbindattribute(shaderprogram, 0, "position") //bind "in position" location 0 //link shader program gllinkprogram(shaderprogram);
- after linking, , while building vaos (or drawing geometry), query location of attributes, , set buffers accordingly:
you glgetattriblocation
function.
gluint positionloc = glgetattriblocation(shaderprogram, "position");// ask location of attribute "position //create buffers , transfer data... glbindbuffer(gl.array_buffer, ...); glbufferdata(...); //turns on vertex attribute "position" glenablevertexattribarray(positionloc); //set pointer between buffer , attribute glvertexattribpointer(positionloc,...);
for performance reasons, first option recommended, doesn't force flush.
Comments
Post a Comment