c# - Problems with attribute binding and shaders -
currently i'm upgrading our opengl-engine new shading , attribute scheme more dynamic , not somehow static in usage , programming.
for i'm replacing old vertexbuffer class new bufferrenderer multiple databuffer ( renderdatabuffer, renderindexbuffer ) objects assigned, holding rendering data. new scheme allows instancing gldrawelementsinstanced , static rendering gldrawelements.
it looks attribute corrupts existing position attribute , leads unexpected results. tested different settings
test setupthis code sets test data:
_shader = new shader(shadersource.fromfile("instancingshader.xml")); _vertexbuffer = new bufferrenderer(); renderdatabuffer positionbuffer = new renderdatabuffer(arraybuffertarget.array_buffer, arraybufferusage.static_draw, new vertexdeclaration(declarationtype.float, declarationsize.three, attributebindingtype.position)); // set position info of quad positionbuffer.bufferdata(new[] { new vector3(0, 0, 0), new vector3(0, 0, 1), new vector3(1, 0, 0), new vector3(1, 0, 1) }); renderdatabuffer instancebuffer = new renderdatabuffer(arraybuffertarget.array_buffer, arraybufferusage.dynamic_draw, new vertexdeclaration(declarationtype.float, declarationsize.four, attributebindingtype.instancing), new vertexdeclaration(declarationtype.float, declarationsize.four, attributebindingtype.color)); // buffer instance info instancebuffer.bufferdata<instancetestdata>(new[] { new instancetestdata() { color = colors.red, prs = new color(0.1f, 1f, 0.5f, 1) }, new instancetestdata() { color = colors.blue, prs = new color(1f, 1f, 0.5f, 1) }, new instancetestdata() { color = colors.green, prs = new color(0.1f, 1f, 1f, 1) }, new instancetestdata() { color = colors.yellow, prs = new color(1f, 1f, 1f, 1) } }); // set index buffer indexed rendering renderindexbuffer indiciesbuffer = new renderindexbuffer(type: indiciestype.unsigned_byte); indiciesbuffer.bufferdata(new byte[] { 2, 1, 0, 1, 2, 3 }); // register buffers ( sec parameter used glvertexattribdivisor ) _vertexbuffer.addbuffer(positionbuffer); _vertexbuffer.addbuffer(instancebuffer, 1); _vertexbuffer.indexbuffer = indiciesbuffer; the vertex shader ( pixel outputs color ):
uniform mat4 umodelviewprojection; varying vec4 vcolor; attribute vec3 aposition; // position0 attribute vec4 acolor; // color 0 attribute vec4 ainstanceposition; // instancing0 void main() { gl_position = umodelviewprojection * vec4(vec2((aposition.x * 20) + (gl_instanceid * 20), aposition.z * 20), -3, 1); vcolor = acolor; } rendering ( pseudocode simplify reading; not final performance guys out there ) gluseprogram foreach (parameter in shader_parameters) gluniformx foreach (buffer in render_buffers) glbindbuffer foreach (declaration in buffer.vertex_declarations) if (shader.exists(declaration)) // check if declaration exists in shader glenablevertexattribarray(shader.attributelocation(declaration)) glvertexattribpointer if (instancedivisor != null) glvertexattribdivisor glbindbuffer(index_buffer) gldrawelementsinstanced shader attribute binding the shader attribute binding done @ initialization , looks this:
_vertexattributes = source.attributes.toarray(); (uint = 0; < _vertexattributes.length; i++) { shaderattribute attribute = _vertexattributes[i]; glshaders.bindattriblocation(_shaderhandle, i, attribute.name); } so there should not attribute aliasing in shader, each of them gets unique number ( matrices not implemented yet, know require more 1 index, i'm not using them vertex attributes right ). mentioned in comment, filter attributes after linking shader no location bound not exists.
this code attribute binding:
bind(); int32 offset = 0; (uint32 = 0; < _declarations.length; i++) { vertexdeclaration info = _declarations[i]; shaderattributelocation location; if (shader.getattributelocation(data.binding, out location)) { glvertexbuffer.enablevertexattribarray(location); glvertexbuffer.vertexattribpointer(location, (attributesize)data.size, (attributetype)data.type, data.normalized, _stridesize, new intptr(offset)); if (instancedivisor != null) glvertexbuffer.vertexattribdivisor(location, instancedivisor.value); } offset += data.componentsize; } test results the results seen here:
now, if alter binding on code side ( attributebindingtype.color <-> attributebindingtype.instancing ) looks this:
if alter vcolor = acolor; vcolor = ainstanceposition; results simple: instead of having multiple little quads color have 1 big fullscreen quad red. locations of each of attributes different others technically values should correct, seem not. using both attributes in shader doesn't solve problem.
i'm searching thought or solution solve problem.
tracking problem downi've started track downwards more , more, complex code costs me hours found something: shader i'm using working when leave out attribute index 0 when calling bindattriblocation. other words workaround works specified shader:
foreach (attribute in vertexattributes) { if (shader == problemshader) // index of attribute glbindattriblocation(_shaderhandle, + 1, attribute.name); // other shaders else glbindattriblocation(_shaderhandle, i, attribute.name); } i guess has either instancing or multiple vbo's i'm using instancing. differences normal shaders. normal ones working when start attribute location index @ 0, not working when starting @ 1.
i found solution problem , has been simple. after rendering instancing need phone call glvertexattribdivisor(location, 0); on attributes had divisor enabled before.
c# opengl
No comments:
Post a Comment