protected internal override void Render(Scenes.Scene scene, Cameras.Camera camera, int viewportWidth, int viewportHeight) { sprites.Clear(); scene.TraverseVisible(c => { var sprite = c as Sprite; if (sprite != null) sprites.Add(sprite); }); if (sprites.Count == 0) return; // setup gl GL.UseProgram( program ); GL.EnableVertexAttribArray( attributes.position ); GL.EnableVertexAttribArray( attributes.uv ); GL.Disable( EnableCap.CullFace); GL.Enable( EnableCap.Blend); GL.BindBuffer( BufferTarget.ArrayBuffer, vertexBuffer ); GL.VertexAttribPointer( attributes.position, 2, VertexAttribPointerType.Float, false, 2 * 8, 0 ); GL.VertexAttribPointer( attributes.uv, 2, VertexAttribPointerType.Float, false, 2 * 8, 8 ); GL.BindBuffer(BufferTarget.ElementArrayBuffer, elementBuffer ); GL.UniformMatrix4(uniforms.projectionMatrix, 16, false, camera.projectionMatrix.elements); GL.ActiveTexture(TextureUnit.Texture0); GL.Uniform1( uniforms.map, 0 ); var oldFogType = 0; var sceneFogType = 0; var fog = scene.Fog; if (fog != null) { GL.Uniform3(uniforms.fogColor, scene.Fog.Color.R, scene.Fog.Color.G, scene.Fog.Color.B); var linear = fog as FogLinear; var exp2 = fog as FogExp2; if (linear != null) { GL.Uniform1( uniforms.fogNear, linear.Near); GL.Uniform1( uniforms.fogFar, linear.Far); GL.Uniform1( uniforms.fogType, 1 ); oldFogType = 1; sceneFogType = 1; } else if ( exp2 != null) { GL.Uniform1( uniforms.fogDensity, exp2.Density); GL.Uniform1( uniforms.fogType, 2 ); oldFogType = 2; sceneFogType = 2; } } else { GL.Uniform1( uniforms.fogType, 0 ); oldFogType = 0; sceneFogType = 0; } // update positions and sort foreach( var sprite in sprites) { var material = sprite.Material; sprite.modelViewMatrix.MultiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld ); sprite.Zdepth = -sprite.modelViewMatrix.elements[ 14 ]; } sprites.Sort( PainterSortStable ); // render all sprites foreach( var sprite in sprites) { var material = sprite.Material as SpriteMaterial; GL.Uniform1( uniforms.alphaTest, material.ShouldAlphaTest); GL.UniformMatrix4( (int)uniforms.modelViewMatrix, 16, false, sprite.modelViewMatrix.elements ); var fogType = 0; if ( scene.Fog != null && material.UseFog) fogType = sceneFogType; if ( oldFogType != fogType ) { GL.Uniform1( uniforms.fogType, fogType ); oldFogType = fogType; } if ( material.DiffuseMap != null ) { GL.Uniform2(uniforms.uvOffset, material.DiffuseMap.Offset.x, material.DiffuseMap.Offset.y); GL.Uniform2(uniforms.uvScale, material.DiffuseMap.Repeat.x, material.DiffuseMap.Repeat.y); } else { GL.Uniform2( uniforms.uvOffset, 0, 0 ); GL.Uniform2( uniforms.uvScale, 1, 1 ); } GL.Uniform1( uniforms.opacity, material.Opacity ); GL.Uniform3(uniforms.color, material.Diffuse.R, material.Diffuse.G, material.Diffuse.B); GL.Uniform1( uniforms.rotation, material.Rotation); GL.Uniform2( uniforms.scale, sprite.Scale.x, sprite.Scale.y); renderer.SetBlending( material.Blending, material.BlendEquation, material.BlendSource, material.BlendDestination); renderer.DepthTest = material.ShouldDepthTest; renderer.DepthWrite = material.ShouldDepthWrite; if ( material.DiffuseMap != null && material.DiffuseMap.Resolution.Width > 0) renderer.SetTexture( material.DiffuseMap, 0 ); else renderer.SetTexture(texture, 0 ); GL.DrawElements( BeginMode.TriangleFan, 6, DrawElementsType.UnsignedShort, 0 ); } // restore gl GL.Enable( EnableCap.CullFace); }