c# - How exactly do we bind an attribute name to a location in OpenGL? -
i using opentk, wrapper .net. version of opengl used 4.5 implemented nvidia. using windows 10 pro.
issue
my issue simple. want address vertex attributes names, instead of hard coding location in shader source.
i have vertex shader called basictexturedvert.glsl
#version 450 core in vec4 position; in vec2 normal; uniform mat4 modelmatrix; uniform mat4 viewmatrix; uniform mat4 projectionmatrix; out vec2 vs_uv; void main(void) { vs_uv = normal; gl_position = projectionmatrix * viewmatrix * modelmatrix * position; } things have tried
now that, have gl.getattriblocation name of attribute in program , return location of it. tried returns location of in vec4 position , not of in vec2 normal. , mean:
- when hard code location of both attributes,
gl.getattriblocation("position")returns correct location, samenormalreturns-1. - i thought had name of
normal, maybe reserved word opengl, changed random wordabcdefstill gives same result. - now thinking maybe has order of declaration of shader attributes in shader source, move
normalbeforeposition, still same results. - about going insane trying figure why opengl giving right location
position. thought maybevec2(which here differentiator between two) not accepted type, check online, damn accepted.
as can see tried many things before trying one. read can programmatically bind attributes names , assign location choose. here in following code.
first create shader objects this:
var basictexturedvertexshader = new shader("basic textured vertex shader", shadertype.vertexshader, file.readalltext(@"components\shaders\vertex\basictexturedvert.glsl"), new[] { "position", "normal" } ); var basictexturedfragmentshader = new shader("basic textured fragment shader", shadertype.fragmentshader, file.readalltext(@"components\shaders\fragment\basictexturedfrag.glsl") ); as can see, each shader gets assigned: - name can understand shader working on (during debug) - type of shader (vertexshader or fragmentshader) - shader source code - , optionally array containing names of shader attributes first 1 new[] { "position", "normal" } assigned location during program linking
i create program , link them it:
_texturedprogram = new shaderprogram(basictexturedvertexshader, basictexturedfragmentshader); _texturedprogram.link(); now inside _texturedprogram.link:
int location = 0; // location index starts 0 goes foreach (var shader in _shaders) { debugutil.info($"attaching shader {shader.name} of handle {shader.handle} of type {shader.type} program {_handle}"); gl.attachshader(_handle, shader.handle); // if shader attached has attribute names // means need give them location if (shader.attributenames != null) { foreach (var shaderattributename in shader.attributenames) { _attributelocation[shaderattributename] = location; gl.bindattriblocation(_handle, location, shaderattributename); // check if wrong happened , output errorcode error; bool errorhappened = false; while ((error = gl.geterror()) != errorcode.noerror) { debugutil.warning($"problem during binding attrib location of {shaderattributename} of {shader.name} {location} in program {_handle}. error: {error}"); errorhappened = true; } if (!errorhappened) { debugutil.info($"shader attribute \"{shaderattributename}\" of {shader.name} of program {handle} should have been bound location {location}"); } location++; } } } // link program gl.linkprogram(_handle); // make sure linking happened no problem var info = gl.getprograminfolog(_handle); if (!string.isnullorwhitespace(info)) { debugutil.warning($"info log during linking of shaders program {_handle}: {info}"); } else { debugutil.info($"program {_handle} linked successfully"); } // compare locations think have been assigned vertex attributes // 1 stored in opengl foreach (var attribute in _attributelocation) { debugutil.info($"[program:{_handle}] according opengl, {attribute.key} located in {gl.getattriblocation(_handle, attribute.key)} when supposed in {attribute.value}"); } // clean :) foreach (var shader in _shaders) { gl.detachshader(_handle, shader.handle); gl.deleteshader(shader.handle); } // no need shaders anymore _shaders.clear(); and here console output:
lets position's default position have been 0 , coincidence. let's set location starting index @ 5.
as can see, code works position not normal...
it appears that, because normal vertex attribute leads no use in subsequent stage (= fragment shader), opengl optimizes shader program getting rid of unused variables.
thanks @ripi2 pointing out.


Comments
Post a Comment