OSDN Git Service

Update copyright year
[radegast/radegast.git] / Radegast / GUI / Rendering / Shader.cs
1 // 
2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2014, Radegast Development Team
4 // All rights reserved.
5 // 
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 
9 //     * Redistributions of source code must retain the above copyright notice,
10 //       this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //     * Neither the name of the application "Radegast", nor the names of its
15 //       contributors may be used to endorse or promote products derived from
16 //       this software without specific prior CreateReflectionTexture permission.
17 // 
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 // $Id$
30 //
31
32 using System;
33 using System.Collections.Generic;
34 using System.Linq;
35 using System.Text;
36 using System.IO;
37 using OpenMetaverse;
38 using OpenTK.Graphics.OpenGL;
39
40 namespace Radegast.Rendering
41 {
42     public class Shader : IDisposable
43     {
44         public int ID = -1;
45
46         public bool Load(string fileName)
47         {
48             if (!RenderSettings.HasShaders) return false;
49
50             try
51             {
52                 ShaderType type;
53
54                 string code = File.ReadAllText(fileName);
55                 if (fileName.EndsWith(".vert"))
56                 {
57                     type = ShaderType.VertexShader;
58                 }
59                 else if (fileName.EndsWith(".frag"))
60                 {
61                     type = ShaderType.FragmentShader;
62                 }
63                 else
64                     return false;
65
66                 ID = GL.CreateShader(type);
67                 GL.ShaderSource(ID, code);
68                 GL.CompileShader(ID);
69                 string info = GL.GetShaderInfoLog(ID);
70                 int res;
71                 GL.GetShader(ID, ShaderParameter.CompileStatus, out res);
72                 if (res != 1)
73                 {
74                     Logger.DebugLog("Compilation failed: " + info);
75                     ID = -1;
76                     return false;
77                 }
78                 Logger.DebugLog(string.Format("{0} {1} compiled successfully", type.ToString(), fileName));
79                 return true;
80             }
81             catch
82             {
83                 return false;
84             }
85         }
86
87         public void Dispose()
88         {
89             if (!RenderSettings.HasShaders) return;
90
91             if (ID == -1) return;
92             GL.DeleteShader(ID);
93         }
94     }
95
96     public class ShaderProgram : IDisposable
97     {
98         public static int CurrentProgram = 0;
99         public int ID = -1;
100         Shader[] shaders;
101
102         public bool Load(params string[] shaderNames)
103         {
104             if (!RenderSettings.HasShaders) return false;
105
106             shaders = new Shader[shaderNames.Length];
107             for (int i = 0; i < shaderNames.Length; i++)
108             {
109                 Shader s = new Shader();
110                 if (!s.Load(Path.Combine("shader_data", shaderNames[i])))
111                     return false;
112                 shaders[i] = s;
113             }
114
115             ID = GL.CreateProgram();
116             for (int i = 0; i < shaders.Length; i++)
117             {
118                 GL.AttachShader(ID, shaders[i].ID);
119             }
120             GL.LinkProgram(ID);
121             int res;
122             GL.GetProgram(ID, ProgramParameter.LinkStatus, out res);
123             if (res != 1)
124             {
125                 Logger.DebugLog("Linking shader program failed!");
126                 return false;
127             }
128
129             Logger.DebugLog(string.Format("Linking shader program consitsting of {0} shaders successful", shaders.Length));
130             return true;
131         }
132
133         public void Start()
134         {
135             if (!RenderSettings.HasShaders) return;
136
137             if (ID != -1)
138             {
139                 GL.UseProgram(ID);
140                 CurrentProgram = ID;
141             }
142         }
143
144         public static void Stop()
145         {
146             if (!RenderSettings.HasShaders) return;
147             
148             if (CurrentProgram != 0)
149             {
150                 GL.UseProgram(0);
151             }
152         }
153
154         public int Uni(string var)
155         {
156             if (!RenderSettings.HasShaders) return -1;
157
158             return GL.GetUniformLocation(ID, var);
159         }
160
161         public void SetUniform1(string var, int value)
162         {
163             if (!RenderSettings.HasShaders || ID < 1) return;
164             int varID = Uni(var);
165             if (varID == -1)
166             {
167                 return;
168             }
169             GL.Uniform1(varID, value);
170         }
171
172         public void SetUniform1(string var, float value)
173         {
174             if (!RenderSettings.HasShaders || ID < 1) return;
175             int varID = Uni(var);
176             if (varID == -1)
177             {
178                 return;
179             }
180             GL.Uniform1(varID, value);
181         }
182
183         public void Dispose()
184         {
185             if (!RenderSettings.HasShaders) return;
186
187             if (ID != -1)
188             {
189                 if (CurrentProgram == ID)
190                 {
191                     GL.UseProgram(0);
192                 }
193                 GL.DeleteProgram(ID);
194                 ID = -1;
195             }
196
197             if (shaders != null)
198             {
199                 for (int i = 0; i < shaders.Length; i++)
200                 {
201                     shaders[i].Dispose();
202                 }
203             }
204             shaders = null;
205         }
206     }
207 }