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;
        }
Exemple #2
0
        /// <summary>
        /// Activates the Current Vertex/Pixel shader pair into a program.
        /// </summary>
        private void ActivateShaderProgram()
        {
            // Lookup the shader program.
            ShaderProgram program = programCache.GetProgram(VertexShader, PixelShader);

            if (program.Program == -1)
            {
                return;
            }

            // Set the new program if it has changed.
            if (shaderProgram != program)
            {
                GL.UseProgram(program.Program);
                shaderProgram = program;
            }

            int 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[0] = 1.0f;
            posFixup[1] = 1.0f;
            posFixup[2] = (63.0f / 64.0f) / Viewport.Width;
            posFixup[3] = -(63.0f / 64.0f) / Viewport.Height;

            // Flip vertically if we have a render target bound (rendering offscreen)
            if (RenderTargetCount > 0)
            {
                posFixup[1] *= -1.0f;
                posFixup[3] *= -1.0f;
            }

            GL.Uniform4(posFixupLoc, 1, posFixup);
        }
 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();
 }