SharpGL着色器使用

最近项目中有用到sharpgl相关内容,发现网上相关资料较少,希望能对大家有所帮助

下面首先介绍着色器的使用,在红宝书(第七版)15章中,有相关介绍。我们可以编写相应着色应用程序,从而使gpu调用我们自己写的顶点着色和片段着色器。

下面测试程序中,shaderhelper为编写的顶点着色器和片段着色器代码。其中顶点着色器接收位置、颜色、法线信息、位置偏移、灯光方向信息。

注意事项:

1、红宝书中15.9节中,介绍到GSGL 1.3版本内置了众多全局变量,可以很方便供我们使用,但是这些变量再高版本GSGL如330或430中无法使用。

如果想继续使用,可将改为兼容模式,即可使用。或者自行计算相关矩阵或向量

#version 430 compatibility

2、着色器代码的编译很容易产生问题,所以错误信息的输出尤为重要。

 

3、SharpGL类库中也提供了相应的顶点着色器类

 

 

ShaderBuilder为编译着色器代码类。主要完成着色器代码的编译链接生成

using SharpGL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MultiSurveyLib
{
    public class ShaderHelper
    {
        /// <summary>
        /// 顶点着色器代码
        /// </summary>
        public static string VertexShaderSource =
            "#version 430 compatibility\n" +
            "uniform vec4 offset;\n" +
            "uniform vec3 lightDir;\n" +
            "layout(location=0) in vec3 position;\n" +
            "layout(location=1) in vec3 color;\n" +
            "layout(location=2) in vec3 normal;\n" +
            "out vec4 colorOut;\n" +
            "void main()\n" +
            "{\n" +
                "vec4 pos = vec4(position,1) - offset;" +
                "gl_Position = gl_ModelViewProjectionMatrix * pos;\n" +
                "vec3 N = normalize(gl_NormalMatrix * normal);" +
                "vec4 V = gl_ModelViewMatrix * pos;" +
                "float diffuse = max(0.0, dot(N, lightDir));" +
                "colorOut = diffuse*vec4(color,1) * vec4(0.75,0.75,0.75,1);" +
            "}\n";

        /// <summary>
        /// 片段着色器代码
        /// </summary>
        public static string FragmentShaderSource =
             "#version 430 compatibility\n" +
             "in vec4 colorOut;\n" +
             "out vec4 color1;\n" +
             "void main()\n" +
             "{" +
                "color1 = colorOut;" +         
             "}\n"; 
    }

    public class ShaderBuilder
    {
        private uint program = 0;
        private uint vertexShader = 0;
        private uint fragmentShader = 0;
        public ShaderBuilder()
        {

        }
        public uint BuildProgram(OpenGL gl, string vertexShaderSource = null, string fragmentShaderSource = null)
        {
            if (vertexShaderSource == null && fragmentShaderSource == null)
            {
                vertexShader = gl.CreateShader(OpenGL.GL_VERTEX_SHADER);
                gl.ShaderSource(vertexShader, ShaderHelper.VertexShaderSource);
                gl.CompileShader(vertexShader);
                string compileInfo = GetShaderCompilorStatus(gl, vertexShader);

                fragmentShader = gl.CreateShader(OpenGL.GL_FRAGMENT_SHADER);
                gl.ShaderSource(fragmentShader, ShaderHelper.FragmentShaderSource);
                gl.CompileShader(fragmentShader);

                GetShaderCompilorStatus(gl, fragmentShader);

                program = gl.CreateProgram();
                gl.AttachShader(program, vertexShader);
                gl.AttachShader(program, fragmentShader);
                gl.LinkProgram(program);
                GetProgramLinkedInfoLog(gl, program);
                gl.ValidateProgram(program);
            }
            return program;
        }
        /// <summary>
        /// 查看GLSL程序着色器编译信息
        /// </summary>
        /// <param name="gl"></param>
        /// <param name="shader">片段着色器或顶点着色器</param>
        /// <returns></returns>
        private string GetShaderCompilorStatus(OpenGL gl, uint shader)
        {
            int[] status = { -1 };
            gl.GetShader(shader, OpenGL.GL_COMPILE_STATUS, status);
            if (status[0] == 0)
            {
                StringBuilder sb = new StringBuilder(100);
                gl.GetShaderInfoLog(shader, 500, IntPtr.Zero, sb);
                Console.WriteLine(sb);
                return sb.ToString();
            }
            else
                return "";
        }
        /// <summary>
        /// 获取GLSL程序链接信息
        /// </summary>
        /// <param name="gl"></param>
        /// <param name="program"></param>
        /// <returns></returns>
        private string GetProgramLinkedInfoLog(OpenGL gl, uint program)
        {
            int[] status = { -1 };
            gl.GetProgram(program, OpenGL.GL_LINK_STATUS, status);
            if (status[0] == 0)
            {
                StringBuilder sb = new StringBuilder(100);
                gl.GetProgramInfoLog(program, 500, IntPtr.Zero, sb);
                Console.WriteLine(sb.ToString());
                return sb.ToString();
            }
            else
                return "";
        }
        public void Dispose(OpenGL gl)
        {
            if (program != 0)
            {
                gl.DeleteShader(vertexShader);
                gl.DeleteShader(fragmentShader);
                gl.DeleteProgram(program);
            }
        }
    }
}

下面为上面的测试程序
 ShaderBuilder sb = new ShaderBuilder();//初始化着色器
  uint program = sb.BuildProgram(gl);//gl为自己创建的OpenGL对象
初始化一次即可。
下面为绘制代码
int offsetLocation = -1;
if (Win32.wglGetCurrentContext().ToInt32() != 0)
{
   gl.UseProgram(program);
   offsetLocation = gl.GetUniformLocation(program, "offset");
   int lightindex = gl.GetUniformLocation(program, "lightDir");
   if (lightindex != -1)
   {
      glRedrawGrid.Uniform3(lightindex, 1, new float[] { 1, 1, 1 });//设置平行光源方向
    }
    }
    else
    {
         Console.WriteLine("context error "+ "  "+gl.GetErrorCode());
    }
//设置偏移位置,主要针对于大坐标频繁计算,此次传入偏移坐标即可
  gl.Uniform4(offsetLocation, 1, new float[] { ofx, ofy, 0, 0 });//ofx ofy为偏移坐标
  modelObj.Draw(gl);//vao方式绘制数据
}

 

 

 

 

 

 


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值