internal void SetConstantBuffers(GraphicsDevice device, ShaderProgram shaderProgram) #endif { // If there are no constant buffers then skip it. if (_valid == 0) return; var valid = _valid; for (var i = 0; i < _buffers.Length; i++) { var buffer = _buffers[i]; if (buffer != null && !buffer.IsDisposed) { #if DIRECTX buffer.PlatformApply(device, _stage, i); #elif OPENGL || PSM || WEB buffer.PlatformApply(device, shaderProgram); #endif } // Early out if this is the last one. valid &= ~(1 << i); if (valid == 0) return; } }
public MonoGameSpriteBatchUnpacked(GraphicsContext context, int size) { _context = context; Size = size; _indexArray = new ushort[6 * size]; for (int i = 0; i < size; i++) { _indexArray[i * 6 + 0] = (ushort)(i * 4); _indexArray[i * 6 + 1] = (ushort)(i * 4 + 1); _indexArray[i * 6 + 2] = (ushort)(i * 4 + 2); _indexArray[i * 6 + 3] = (ushort)(i * 4 + 1); _indexArray[i * 6 + 4] = (ushort)(i * 4 + 3); _indexArray[i * 6 + 5] = (ushort)(i * 4 + 2); } _vertexArrayVector = new Vector2[4 * size]; _vertexArrayColor = new VertexElementColor[4 * size]; _vertexArrayTexture = new Vector2[4 * size]; _vertexBuffer = new VertexBuffer(4 * size, 6 * size, VertexFormat.Float2, VertexFormat.UByte4N, VertexFormat.Float2); _vertexBuffer.SetIndices(_indexArray, 0, 0, 6 * size); _shader = new ShaderProgram("/Application/shaders/Texture.cgx"); }
public MonoGameSpriteBatchNoIndex(GraphicsContext context, int size) { _context = context; Size = size; _vertexArray = new VertexPosition2ColorTexture[4 * size]; _vertexBuffer = new VertexBuffer(4 * size, VertexFormat.Float2, VertexFormat.UByte4N, VertexFormat.Float2); _shader = new ShaderProgram("/Application/shaders/Texture.cgx"); }
public unsafe void PlatformApply(GraphicsDevice device, ShaderProgram program) { // NOTE: We assume here the program has // already been set on the device. // If the program changed then lookup the // uniform again and apply the state. if (_shaderProgram != program) { var location = program.GetUniformLocation(_name); if (location == -1) return; _shaderProgram = program; _location = location; _dirty = true; } // If the shader program is the same, the effect may still be different and have different values in the buffer if (!Object.ReferenceEquals(this, _lastConstantBufferApplied)) _dirty = true; // If the buffer content hasn't changed then we're // done... use the previously set uniform state. if (!_dirty) return; fixed (byte* bytePtr = _buffer) { // TODO: We need to know the type of buffer float/int/bool // and cast this correctly... else it doesn't work as i guess // GL is checking the type of the uniform. #if SDL2 device.GLDevice.glUniform4fv( _location, _buffer.Length / 16, (IntPtr) bytePtr ); #else GL.Uniform4(_location, _buffer.Length / 16, (float*)bytePtr); #endif } // Clear the dirty flag. _dirty = false; _lastConstantBufferApplied = this; }
internal EffectPass(Effect effect, EffectPass cloneSource) { Debug.Assert(effect != null, "Got a null effect!"); Debug.Assert(cloneSource != null, "Got a null cloneSource!"); _effect = effect; // Share all the immutable types. Name = cloneSource.Name; _blendState = cloneSource._blendState; _depthStencilState = cloneSource._depthStencilState; _rasterizerState = cloneSource._rasterizerState; Annotations = cloneSource.Annotations; _vertexShader = cloneSource._vertexShader; _pixelShader = cloneSource._pixelShader; #if PSM _shaderProgram = cloneSource._shaderProgram; #endif }
internal EffectParameter EffectParameterForUniform(ShaderProgram shaderProgram, int index) { //var b = shaderProgram.GetUniformBinding(i); var name = shaderProgram.GetUniformName(index); //var s = shaderProgram.GetUniformSize(i); //var x = shaderProgram.GetUniformTexture(i); var type = shaderProgram.GetUniformType(index); //EffectParameter.Semantic => COLOR0 / POSITION0 etc //FIXME: bufferOffset in below lines is 0 but should probably be something else switch (type) { case ShaderUniformType.Float4x4: return new EffectParameter( EffectParameterClass.Matrix, EffectParameterType.Single, name, 4, 4, "float4x4",EffectAnnotationCollection.Empty, EffectParameterCollection.Empty, EffectParameterCollection.Empty, new float[4 * 4]); case ShaderUniformType.Float4: return new EffectParameter( EffectParameterClass.Vector, EffectParameterType.Single, name, 4, 1, "float4",EffectAnnotationCollection.Empty, EffectParameterCollection.Empty, EffectParameterCollection.Empty, new float[4]); case ShaderUniformType.Sampler2D: return new EffectParameter( EffectParameterClass.Object, EffectParameterType.Texture2D, name, 1, 1, "texture2d",EffectAnnotationCollection.Empty, EffectParameterCollection.Empty, EffectParameterCollection.Empty, null); default: throw new Exception("Uniform Type " + type + " Not yet implemented (" + name + ")"); } }
private void Link(Shader vertexShader, Shader pixelShader) { // NOTE: No need to worry about background threads here // as this is only called at draw time when we're in the // main drawing thread. var program = GL.CreateProgram(); GraphicsExtensions.CheckGLError(); GL.AttachShader(program, vertexShader.GetShaderHandle()); GraphicsExtensions.CheckGLError(); GL.AttachShader(program, pixelShader.GetShaderHandle()); GraphicsExtensions.CheckGLError(); //vertexShader.BindVertexAttributes(program); GL.LinkProgram(program); GraphicsExtensions.CheckGLError(); GL.UseProgram(program); GraphicsExtensions.CheckGLError(); vertexShader.GetVertexAttributeLocations(program); pixelShader.ApplySamplerTextureUnits(program); var linked = 0; GL.GetProgram(program, GetProgramParameterName.LinkStatus, out linked); GraphicsExtensions.LogGLError("VertexShaderCache.Link(), GL.GetProgram"); if (linked == 0) { var log = GL.GetProgramInfoLog(program); Console.WriteLine(log); GL.DetachShader(program, vertexShader.GetShaderHandle()); GL.DetachShader(program, pixelShader.GetShaderHandle()); #if MONOMAC GL.DeleteProgram(1, ref program); #else GL.DeleteProgram(program); #endif throw new InvalidOperationException("Unable to link effect program"); } ShaderProgram shaderProgram = new ShaderProgram(program); _programCache.Add(vertexShader.HashKey | pixelShader.HashKey, shaderProgram); }
private void PlatformClear() { // Force the uniform location to be looked up again _shaderProgram = null; }
public unsafe void PlatformApply(GraphicsDevice device, ShaderProgram program) { #warning Unimplemented }
private static void SetEffectParameter(ShaderProgram program, EffectParameter param) { if (param.Name == "posFixup") return; int location = program.GetUniformLocation(param.Name); switch (param.ParameterClass) { case EffectParameterClass.Object: SetEffectParameterObject(program,location, param); break; case EffectParameterClass.Vector: SetEffectParameterVector(program, location, param); break; case EffectParameterClass.Matrix: SetEffectParameterMatrix(program,location, param); break; case EffectParameterClass.Scalar: SetEffectParameterFloat(program, location, param); break; } GraphicsExtensions.CheckGLError(); }
private static void SetEffectParameterVector(ShaderProgram program,int location, EffectParameter param) { //int elementCount = param.RowCount * param.ColumnCount; unsafe { float[] objArray = (float[])param.Data; fixed (float* data = objArray) { if (objArray.Length == 2) GL.Uniform2(location, 1, data); else if(objArray.Length == 3) GL.Uniform3(location, 1, data); else GL.Uniform4(location, 1, data); } } }
private static void SetEffectParameterMatrix(ShaderProgram program, int location, EffectParameter param) { //int elementCount = param.RowCount * param.ColumnCount; unsafe { float[] objArray = (float[])param.Data; fixed (float* data = objArray) { GL.UniformMatrix4(location, 1,false, data); } } }
private static void SetEffectParameterObject(ShaderProgram program,int location,EffectParameter param) { object obj = param.Data; }
private void Link(Shader vertexShader, Shader pixelShader) { // NOTE: No need to worry about background threads here // as this is only called at draw time when we're in the // main drawing thread. var program = vertexShader.GraphicsDevice.GLDevice.glCreateProgram(); vertexShader.GraphicsDevice.GLDevice.glAttachShader(program, vertexShader.GetShaderHandle()); vertexShader.GraphicsDevice.GLDevice.glAttachShader(program, pixelShader.GetShaderHandle()); vertexShader.GraphicsDevice.GLDevice.glLinkProgram(program); vertexShader.GraphicsDevice.GLDevice.glUseProgram(program); vertexShader.GetVertexAttributeLocations(program); pixelShader.ApplySamplerTextureUnits(program); var linked = 0; vertexShader.GraphicsDevice.GLDevice.glGetProgramiv( program, OpenGLDevice.GLenum.GL_LINK_STATUS, out linked ); if (linked == 0) { Console.WriteLine( vertexShader.GraphicsDevice.GLDevice.glGetProgramInfoLog(program) ); vertexShader.GraphicsDevice.GLDevice.glDetachShader(program, vertexShader.GetShaderHandle()); vertexShader.GraphicsDevice.GLDevice.glDetachShader(program, pixelShader.GetShaderHandle()); vertexShader.GraphicsDevice.GLDevice.glDeleteProgram(program); throw new InvalidOperationException("Unable to link effect program"); } ShaderProgram shaderProgram = new ShaderProgram(program); _programCache.Add(vertexShader.HashKey | pixelShader.HashKey, shaderProgram); }
/// <summary> /// Activates the Current Vertex/Pixel shader pair into a program. /// </summary> private void ActivateShaderProgram() { // Lookup the shader program. var shaderProgram = _programCache.GetProgram(VertexShader, PixelShader); if (shaderProgram.Program == -1) { return; } // Set the new program if it has changed. if (_shaderProgram != shaderProgram) { GL.UseProgram(shaderProgram.Program); GraphicsExtensions.CheckGLError(); _shaderProgram = shaderProgram; } var posFixupLoc = shaderProgram.GetUniformLocation("posFixup"); if (posFixupLoc == -1) { return; } // Apply vertex shader fix: // The following two lines are appended to the end of vertex shaders // to account for rendering differences between OpenGL and DirectX: // // gl_Position.y = gl_Position.y * posFixup.y; // gl_Position.xy += posFixup.zw * gl_Position.ww; // // (the following paraphrased from wine, wined3d/state.c and wined3d/glsl_shader.c) // // - We need to flip along the y-axis in case of offscreen rendering. // - D3D coordinates refer to pixel centers while GL coordinates refer // to pixel corners. // - D3D has a top-left filling convention. We need to maintain this // even after the y-flip mentioned above. // In order to handle the last two points, we translate by // (63.0 / 128.0) / VPw and (63.0 / 128.0) / VPh. This is equivalent to // translating slightly less than half a pixel. We want the difference to // be large enough that it doesn't get lost due to rounding inside the // driver, but small enough to prevent it from interfering with any // anti-aliasing. // // OpenGL coordinates specify the center of the pixel while d3d coords specify // the corner. The offsets are stored in z and w in posFixup. posFixup.y contains // 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x // contains 1.0 to allow a mad. _posFixup[0] = 1.0f; _posFixup[1] = 1.0f; _posFixup[2] = (63.0f / 64.0f) / Viewport.Width; _posFixup[3] = -(63.0f / 64.0f) / Viewport.Height; //If we have a render target bound (rendering offscreen) if (IsRenderTargetBound) { //flip vertically _posFixup[1] *= -1.0f; _posFixup[3] *= -1.0f; } GL.Uniform4(posFixupLoc, 1, _posFixup); GraphicsExtensions.CheckGLError(); }