Dear Community,
I have written OpenGL application on c++ that uses variance shadow mapping, and that works greate. But I have implemented the same code for OpenTK on C# and the shadow generator shader seems to make the application crush SOMETIMES at the start and SOMETIMES at the end and sometimes it never crushes, and I do not know what is the reason for that, although I am using the same class for generating 2 other shaders and use them and they did not caused any crush, expect this shadow shader it causes a crush without even use it; (Just Initialize and Dispose) but when I comment the code associated with this shader only everything goes well.
Vertex Shadow Shader:
#version 330 core
layout (location = 0) in vec3 vPos;
uniform mat4 lightSpaceMatrix;
uniform mat4 Model;
void main()
{
gl_Position = lightSpaceMatrix * Model * vec4(vPos, 1.0);
}
Fragment Shadow Shader:
#version 330 core
out vec4 FragColor;
void main()
{
float depth = gl_FragCoord.z;
float dx = dFdx(depth);
float dy = dFdy(depth);
float moment2 = depth*depth + 0.25*(dx*dx + dy*dy);
FragColor = vec4(depth, moment2, 0.0, 0.0);
}
and here is the usage of the shader class:
public class RenderingEngine : IDisposable
{
private Shader shadowShaderTest;
private void initializeObjects()
{
//... initialize stuff
shadowShaderTest = new Shader(@"res\shaders\vshadow.vs", @"res\shaders\fshadow.frag");
}
public void Dispose()
{
//...dispose stuff
shadowShaderTest.Dispose();
}
}
and here is the shader class:
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace GraphicsHelper.OpenGL
{
public class Shader : IDisposable
{
private class UniformInfo
{
public String name = "";
public int address = -1;
public int size = 0;
public ActiveUniformType type;
}
private int program_id;
private int uniformCount = 0;
private Dictionary<string, UniformInfo> uniforms;
/// <summary>
/// Gets the program ID.
/// </summary>
public int ProgramID { get => program_id; }
/// <summary>
/// Creates an empty shader program.
/// </summary>
private Shader()
{
program_id = 0;
}
/// <summary>
/// Loads and generate shader program from a given files.
/// </summary>
/// <param name="VertexShaderFilePath">Vertex shader file path</param>
/// <param name="FragmentShaderFilePath">Fragment shader file path</param>
public Shader(string VertexShaderFilePath, string FragmentShaderFilePath)
{
if (!File.Exists(VertexShaderFilePath) || !File.Exists(FragmentShaderFilePath))
throw new FileNotFoundException("ONE OR MORE SHADER FILES NOT FOUND");
DuplicateShader(GenerateProgram(File.ReadAllText(VertexShaderFilePath), File.ReadAllText(FragmentShaderFilePath)), this);
}
private static int CompileShader(string Code, ShaderType Type)
{
int success;
int Shader = GL.CreateShader(Type);
GL.ShaderSource(Shader, Code);
GL.CompileShader(Shader);
GL.GetShader(Shader, ShaderParameter.CompileStatus, out success);
if (success == 0)
{
string InfoLog = GL.GetShaderInfoLog(Shader);
GL.DeleteShader(Shader);
throw new ShaderException("ERROR " + Type.ToString() + " COMPILATION_FAILED" + Environment.NewLine + InfoLog);
}
return Shader;
}
public static Shader GenerateProgram(string VertexShaderCode, string FragmentShaderCode)
{
if (VertexShaderCode == null || FragmentShaderCode == null)
throw new ArgumentNullException();
int program_id = 0;
if (program_id != 0)
GL.DeleteProgram(program_id);
int VertexShader = CompileShader(VertexShaderCode, ShaderType.VertexShader);
if (VertexShader == 0)
throw new ShaderException(ShaderType.VertexShader.ToString() + " COMPILATION FAILED" + Environment.NewLine +
GL.GetShaderInfoLog(VertexShader));
int FragmentShader = CompileShader(FragmentShaderCode, ShaderType.FragmentShader);
if (FragmentShader == 0)
throw new ShaderException(ShaderType.FragmentShader.ToString() + " COMPILATION FAILED" + Environment.NewLine +
GL.GetShaderInfoLog(VertexShader));
program_id = GL.CreateProgram();
GL.AttachShader(program_id, VertexShader);
GL.AttachShader(program_id, FragmentShader);
GL.LinkProgram(program_id);
int success;
GL.GetProgram(program_id, GetProgramParameterName.LinkStatus, out success);
if (success == 0)
{
string InfoLog = GL.GetProgramInfoLog(program_id);
GL.DetachShader(program_id, VertexShader);
GL.DetachShader(program_id, FragmentShader);
GL.DeleteShader(VertexShader);
GL.DeleteShader(FragmentShader);
GL.DeleteProgram(program_id);
throw new ShaderException("ERROR SHADER PROGRAM LINKING_FAILED" + Environment.NewLine + InfoLog);
}
GL.DetachShader(program_id, VertexShader);
GL.DetachShader(program_id, FragmentShader);
GL.DeleteShader(VertexShader);
GL.DeleteShader(FragmentShader);
int uniformCount;
Dictionary<string, UniformInfo> uniforms = new Dictionary<string, UniformInfo>();
GL.GetProgram(program_id, GetProgramParameterName.ActiveUniforms, out uniformCount);
for (int i = 0; i < uniformCount; i++)
{
UniformInfo info = new UniformInfo();
int length = 0;
StringBuilder name = new StringBuilder();
GL.GetActiveUniform(program_id, i, 256, out length, out info.size, out info.type, name);
info.name = name.ToString();
uniforms.Add(name.ToString(), info);
info.address = GL.GetUniformLocation(program_id, info.name);
}
Shader finalProgram = new Shader();
finalProgram.program_id = program_id;
finalProgram.uniformCount = uniformCount;
finalProgram.uniforms = uniforms;
return finalProgram;
}
/// <summary>
/// Make OpenGL use this program object.
/// </summary>
public void Use()
{
GL.UseProgram(program_id);
}
private void DuplicateShader(Shader First, Shader Second)
{
Second.program_id = First.program_id;
Second.uniformCount = First.uniformCount;
Second.uniforms = First.uniforms;
}
/// <summary>
/// Gets the location of specific attribute.
/// </summary>
/// <param name="AttributeName">Attribute name.</param>
/// <returns></returns>
public int GetUniformLocation(string AttributeName)
{
return uniforms[AttributeName].address;
}
private void SetUniform(string UniformName, bool Boolean)
{
GL.Uniform1(GetUniformLocation(UniformName), Boolean ? 1 : 0);
}
private void SetUniform(string UniformName, uint UIntNumber)
{
GL.Uniform1(GetUniformLocation(UniformName), UIntNumber);
}
private void SetUniform(string UniformName, int IntNumber)
{
GL.Uniform1(GetUniformLocation(UniformName), IntNumber);
}
private void SetUniform(string UniformName, float FloatNumber)
{
GL.Uniform1(GetUniformLocation(UniformName), FloatNumber);
}
private void SetUniform(string UniformName, double DoubleNumber)
{
GL.Uniform1(GetUniformLocation(UniformName), DoubleNumber);
}
private void SetUniform(string UniformName, Vector2 Vector2Value)
{
GL.Uniform2(GetUniformLocation(UniformName), Vector2Value);
}
private void SetUniform(string UniformName, float X, float Y)
{
GL.Uniform2(GetUniformLocation(UniformName), X, Y);
}
private void SetUniform(string UniformName, Vector3 Vector3Value)
{
GL.Uniform3(GetUniformLocation(UniformName), Vector3Value);
}
private void SetUniform(string UniformName, float X, float Y, float Z)
{
GL.Uniform3(GetUniformLocation(UniformName), X, Y, Z);
}
private void SetUniform(string UniformName, Vector4 Vector4Value)
{
GL.Uniform4(GetUniformLocation(UniformName), Vector4Value);
}
private void SetUniform(string UniformName, float X, float Y, float Z, float W)
{
GL.Uniform4(GetUniformLocation(UniformName), X, Y, Z, W);
}
private void SetUniform(string UniformName, Matrix2 Matrix2Value, bool Transpose = false)
{
GL.UniformMatrix2(GetUniformLocation(UniformName), Transpose, ref Matrix2Value);
}
private void SetUniform(string UniformName, Matrix3 Matrix3Value, bool Transpose = false)
{
GL.UniformMatrix3(GetUniformLocation(UniformName), Transpose, ref Matrix3Value);
}
private void SetUniform(string UniformName, float M11, float M12, float M13, float M21, float M22, float M23, float M31, float M32, float M33, bool Transpose = false)
{
Matrix3 mat = new Matrix3(M11, M12, M13, M21, M22, M23, M31, M32, M33);
GL.UniformMatrix3(GetUniformLocation(UniformName), Transpose, ref mat);
}
private void SetUniform(string UniformName, Matrix4 Matrix4Value, bool Transpose = false)
{
GL.UniformMatrix4(GetUniformLocation(UniformName), Transpose, ref Matrix4Value);
}
private void SetUniform(string UniformName, float M11, float M12, float M13, float M14, float M21, float M22, float M23, float M24, float M31, float M32, float M33, float M34, float M41, float M42, float M43, float M44, bool Transpose = false)
{
Matrix4 mat = new Matrix4(M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44);
GL.UniformMatrix4(GetUniformLocation(UniformName), Transpose, ref mat);
}
private void SetUniform(string UniformName, Kernel KernelObject)
{
for (int i = 0; i < KernelObject.Length; i++)
SetUniform("kernel[" + i + "]", KernelObject[i]);
}
public object this[string UniformName]
{
set
{
if (uniforms.ContainsKey(UniformName))
{
SetUniform(UniformName, (dynamic)value);
}
}
}
public void Dispose()
{
if (program_id != 0)
GL.DeleteProgram(program_id);
GC.SuppressFinalize(this);
}
}
}