//! On load window (once) protected override void OnLoad() { _version = openGLFactory.NewVersionInformation(Console.WriteLine); _extensions = openGLFactory.NewExtensionInformation(); _debug_callback = openGLFactory.NewDebugCallback(Console.WriteLine); // Version strings _version.Retrieve(); // Get OpenGL extensions _extensions.Retrieve(); // Debug callback _debug_callback.Init(); // Create shader program string vert_shader = @"#version 460 layout (location = 0) in vec2 in_pos; layout (location = 1) in vec2 in_uv; out vec2 vUV; layout (location = 0) uniform mat4 model; layout (location = 1) uniform mat4 projection; void main() { vUV = in_uv.xy; gl_Position = projection * model * vec4(in_pos.xy, 0.0, 1.0); }"; string frag_shader = @"#version 460 in vec2 vUV; layout (binding=0) uniform sampler2D u_texture; layout (location = 2) uniform vec3 textColor; out vec4 fragColor; void main() { vec2 uv = vUV.xy; float text = texture(u_texture, uv).r; fragColor = vec4(textColor.rgb*text, text); }"; this._text_prog = openGLFactory.VertexAndFragmentShaderProgram(vert_shader, frag_shader); this._text_prog.Generate(); this._text_prog.Use(); // load font _font = new FreeTypeFont(32); base.OnLoad(); }
//! On load window (once) protected override void OnLoad() { _version = openGLFactory.NewVersionInformation(Console.WriteLine); _extensions = openGLFactory.NewExtensionInformation(); _debug_callback = openGLFactory.NewDebugCallback(Console.WriteLine); // Version strings _version.Retrieve(); // Get OpenGL extensions _extensions.Retrieve(); // Debug callback _debug_callback.Init(); // create Vertex Array Object, Array Buffer Object and Element Array Buffer Object float[] vquad = { // x y z r g b a -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f }; uint[] iquad = { 0, 1, 2, 0, 2, 3 }; TVertexFormat[] format = { new TVertexFormat(0, 0, 3, 0, false), new TVertexFormat(0, 1, 4, 3, false), }; int vao = GL.GenVertexArray(); GL.BindVertexArray(vao); // Create shader program string vert_shader = @" #version 460 core layout(std430, binding = 0) buffer TVertex { vec4 vertex[]; }; uniform mat4 u_mvp; uniform vec2 u_resolution; uniform float u_thickness; void main() { int line_i = gl_VertexID / 6; int tri_i = gl_VertexID % 6; vec4 va[4]; for (int i=0; i<4; ++i) { va[i] = u_mvp * vertex[line_i+i]; va[i].xyz /= va[i].w; va[i].xy = (va[i].xy + 1.0) * 0.5 * u_resolution; } vec2 v_line = normalize(va[2].xy - va[1].xy); vec2 nv_line = vec2(-v_line.y, v_line.x); vec4 pos; if (tri_i == 0 || tri_i == 1 || tri_i == 3) { vec2 v_pred = normalize(va[1].xy - va[0].xy); vec2 v_miter = normalize(nv_line + vec2(-v_pred.y, v_pred.x)); pos = va[1]; pos.xy += v_miter * u_thickness * (tri_i == 1 ? -0.5 : 0.5) / dot(v_miter, nv_line); } else { vec2 v_succ = normalize(va[3].xy - va[2].xy); vec2 v_miter = normalize(nv_line + vec2(-v_succ.y, v_succ.x)); pos = va[2]; pos.xy += v_miter * u_thickness * (tri_i == 5 ? 0.5 : -0.5) / dot(v_miter, nv_line); } pos.xy = pos.xy / u_resolution * 2.0 - 1.0; pos.xyz *= pos.w; gl_Position = pos; }"; string frag_shader = @" #version 460 core out vec4 fragColor; uniform vec4 u_color; void main() { fragColor = u_color; }"; _test_prog = openGLFactory.VertexAndFragmentShaderProgram(vert_shader, frag_shader); _test_prog.Generate(); mvpLocation = GL.GetUniformLocation(this._test_prog.Object, "u_mvp"); resolutionLocation = GL.GetUniformLocation(this._test_prog.Object, "u_resolution"); thicknessLocation = GL.GetUniformLocation(this._test_prog.Object, "u_thickness"); colorLocation = GL.GetUniformLocation(this._test_prog.Object, "u_color"); _test_prog.Use(); float[] p0 = { -1.0f, -1.0f, 0.0f, 1.0f }; float[] p1 = { 1.0f, -1.0f, 0.0f, 1.0f }; float[] p2 = { 1.0f, 1.0f, 0.0f, 1.0f }; float[] p3 = { -1.0f, 1.0f, 0.0f, 1.0f }; float[] line1 = p3.Concat(p0).Concat(p1).Concat(p2).Concat(p3).Concat(p0).Concat(p1).ToArray(); _lineBuffer1 = openGLFactory.NewStorageBuffer(); _lineBuffer1.Create(line1); _no_vertices_1 = line1.Length / 4; var ll2 = new List <float>(); for (int u = -8; u <= 368; u += 8) { double a = u * Math.PI / 180.0; double c = Math.Cos(a), s = Math.Sin(a); ll2.AddRange(new float[] { (float)c, (float)s, 0.0f, 1.0f }); } float[] line2 = ll2.ToArray(); _lineBuffer2 = openGLFactory.NewStorageBuffer(); _lineBuffer2.Create(line2); _no_vertices_2 = line2.Length / 4; // states GL.ClearColor(0.8f, 0.9f, 1.0f, 1.0f); base.OnLoad(); }
public void Setup(int cx, int cy) { this._cx = cx; this._cy = cy; // Version strings _version.Retrieve(); // Get OpenGL extensions _extensions.Retrieve(); // Debug callback _debug_callback.Init(); // to do mesh buffer creator form multi indices mesh // use in-source wave font file? float[] attributes = { // left -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // right 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 2.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 2.0f, 0.0f, // front -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 3.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 3.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 0.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 3.0f, 0.0f, // back 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 4.0f, 0.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 4.0f, 0.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 4.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 4.0f, 0.0f, // bottom -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 5.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 5.0f, 0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 5.0f, 0.0f, -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 5.0f, 0.0f, // top -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 6.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 6.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 6.0f, 0.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 6.0f, 0.0f }; uint[] indices = { 0, 1, 2, 0, 2, 3, // front 4, 5, 6, 4, 6, 7, // back 8, 9, 10, 8, 10, 11, // left 12, 13, 14, 12, 14, 15, // right 16, 17, 18, 16, 18, 19, // bottom 20, 21, 22, 20, 22, 23 // top }; // create Vertex Array Object, Array Buffer Object and Element Array Buffer Object TVertexFormat[] format = { new TVertexFormat(0, 0, 3, 0, false), new TVertexFormat(0, 1, 4, 3, false), }; _vao = openGLFactory.NewVertexArrayObject(); _vao.AppendVertexBuffer(0, 7, attributes); _vao.Create(format, indices); _vao.Bind(); // Create shader program string vert_shader = @" #version 460 core layout (location = 0) in vec3 inPos; layout (location = 1) in vec4 inAttr; out vec3 vertPos; out vec4 vertTex; out float highlight; layout (std430, binding = 1) buffer UB_MVP { mat4 u_projection; mat4 u_view; mat4 u_model; }; layout (std430, binding = 2) buffer UB_RUBIKS { mat4 u_rubiks_model[27]; int u_cube_hit; int u_side_hit; }; void main() { vec4 tex = inAttr; int cube_i = gl_InstanceID; int color_i = int(tex.z + 0.5); int x_i = cube_i % 3; int y_i = (cube_i % 9) / 3; int z_i = cube_i / 9; if ( color_i == 1 ) tex.z = x_i == 0 ? tex.z : 0.0; else if ( color_i == 2 ) tex.z = x_i == 2 ? tex.z : 0.0; else if ( color_i == 3 ) tex.z = y_i == 0 ? tex.z : 0.0; else if ( color_i == 4 ) tex.z = y_i == 2 ? tex.z : 0.0; else if ( color_i == 5 ) tex.z = z_i == 0 ? tex.z : 0.0; else if ( color_i == 6 ) tex.z = z_i == 2 ? tex.z : 0.0; mat4 model_view = u_view * u_model * u_rubiks_model[cube_i]; vec4 vertex_pos = model_view * vec4(inPos, 1.0); vertPos = vertex_pos.xyz; vertTex = tex; //highlight = tex.z > 0.5 && cube_i == u_cube_hit ? 1.0 : 0.0; //highlight = tex.z > 0.5 && color_i == u_side_hit ? 1.0 : 0.0; highlight = tex.z > 0.5 && cube_i == u_cube_hit && color_i == u_side_hit ? 1.0 : 0.0; gl_Position = u_projection * vertex_pos; }"; string frag_shader = @" #version 460 core in vec3 vertPos; in vec4 vertTex; in float highlight; out vec4 fragColor; vec4 color_table[7] = vec4[7]( vec4(0.5, 0.5, 0.5, 1.0), vec4(1.0, 0.0, 0.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), vec4(0.0, 0.0, 1.0, 1.0), vec4(1.0, 0.5, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0), vec4(1.0, 0.0, 1.0, 1.0) ); void main() { int color_i = int(vertTex.z + 0.5); vec4 color = color_table[color_i]; color.rgb *= max(0.5, highlight); fragColor = color; }"; this._prog = openGLFactory.VertexAndFragmentShaderProgram(vert_shader, frag_shader); this._prog.Generate(); // matrices this._view = Matrix4.LookAt(0.0f, -4.0f, 0.0f, 0, 0, 0, 0, 0, 1); float angle = 70.0f * (float)Math.PI / 180.0f; float aspect = (float)this._cx / (float)this._cy; this._projection = Matrix4.CreatePerspectiveFieldOfView(angle, aspect, 0.1f, 100.0f); // Model view projection shader storage block objects and buffers this._mvp_data = new TMVP(Matrix4.Identity, this._view, this._projection); this._mvp_ssbo = openGLFactory.NewStorageBuffer(); this._mvp_ssbo.Create(ref this._mvp_data); this._mvp_ssbo.Bind(1); T_RUBIKS_DATA rubiks_data = rubiks_data = new T_RUBIKS_DATA(); this._rubiks_ssbo = openGLFactory.NewStorageBuffer(); this._rubiks_ssbo.Create(ref rubiks_data); this._rubiks_ssbo.Bind(2); TLightSource light_source = new TLightSource(new Vector4(-1.0f, -0.5f, -2.0f, 0.0f), 0.2f, 0.8f, 0.8f, 10.0f); this._light_ssbo = openGLFactory.NewStorageBuffer(); this._light_ssbo.Create(ref light_source); this._light_ssbo.Bind(3); this._depth_pack_buffer = openGLFactory.NewPixelPackBuffer(); this._depth_pack_buffer.Create <float>(); // states GL.Viewport(0, 0, this._cx, this._cy); //GL.ClearColor(System.Drawing.Color.Beige); GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.CullFace); GL.FrontFace(FrontFaceDirection.Ccw); GL.CullFace(CullFaceMode.Back); // controller var spin = new ModelSpinningControls( () => { return(this._period); }, () => { return(new float[] { 0, 0, (float)this._cx, (float)this._cy }); }, () => { return(this._view); } ); spin.SetAttenuation(1.0f, 0.05f, 0.0f); _controls = new RubiksMouseControlsProxy(spin); float offset = 2.0f * 1.1f; float scale = 1.0f / 3.0f; this._rubiks_cube = new RubiksControls( () => { return(this._period); }, offset, scale ); int shuffles = 11; this._rubiks_cube.Shuffle(shuffles); double time_s = 1.0; _rubiks_cube.AnimationTime = time_s; }
public void Setup(int cx, int cy) { this._cx = cx; this._cy = cy; // Version strings _version.Retrieve(); // Get OpenGL extensions _extensions.Retrieve(); // Debug callback _debug_callback.Init(); // create Vertex Array Object, Array Buffer Object and Element Array Buffer Object (float[] attributes, uint[] indices) = new Cube().Create(); TVertexFormat[] format = { new TVertexFormat(0, 0, 3, 0, false), new TVertexFormat(0, 1, 3, 3, false), //new TVertexFormat(0, ?, 2, 6, false), new TVertexFormat(0, 2, 4, 8, false), }; _test_vao = openGLFactory.NewVertexArrayObject(); _test_vao.AppendVertexBuffer(0, 12, attributes); _test_vao.Create(format, indices); _test_vao.Bind(); // Create shader program string vert_shader = @"#version 460 core layout (location = 0) in vec4 a_pos; layout (location = 1) in vec3 a_nv; layout (location = 2) in vec4 a_color; layout (location = 0) out TVertexData { vec3 pos; vec3 nv; vec4 col; } outData; layout(std430, binding = 1) buffer MVP { mat4 proj; mat4 view; mat4 model; } mvp; void main() { mat4 mv_mat = mvp.view * mvp.model; mat3 normal_mat = inverse(transpose(mat3(mv_mat))); outData.nv = normalize(normal_mat * a_nv); outData.col = a_color; vec4 viewPos = mv_mat * a_pos; outData.pos = viewPos.xyz / viewPos.w; gl_Position = mvp.proj * viewPos; }"; string frag_shader = @"#version 460 core out vec4 frag_color; layout (location = 0) in TVertexData { vec3 pos; vec3 nv; vec4 col; } inData; layout(std430, binding = 2) buffer TLight { vec4 u_lightDir; float u_ambient; float u_diffuse; float u_specular; float u_shininess; } light_data; void main() { vec3 color = inData.col.rgb; // ambient part vec3 lightCol = light_data.u_ambient * color; vec3 normalV = normalize( inData.nv ); vec3 eyeV = normalize( -inData.pos ); vec3 lightV = normalize( -light_data.u_lightDir.xyz ); // diffuse part float NdotL = max( 0.0, dot( normalV, lightV ) ); lightCol += NdotL * light_data.u_diffuse * color; // specular part vec3 halfV = normalize( eyeV + lightV ); float NdotH = max( 0.0, dot( normalV, halfV ) ); float kSpecular = ( light_data.u_shininess + 2.0 ) * pow( NdotH, light_data.u_shininess ) / ( 2.0 * 3.14159265 ); lightCol += kSpecular * light_data.u_specular * color; frag_color = vec4( lightCol.rgb, inData.col.a ); }"; this._test_prog = openGLFactory.VertexAndFragmentShaderProgram(vert_shader, frag_shader); this._test_prog.Generate(); // Model view projection shader storage block objects and buffers TMVP mvp = new TMVP(Matrix4.Identity, Matrix4.Identity, Matrix4.Identity); this._mvp_ssbo = openGLFactory.NewStorageBuffer(); this._mvp_ssbo.Create(ref mvp); this._mvp_ssbo.Bind(1); TLightSource light_source = new TLightSource(new Vector4(-1.0f, -0.5f, -2.0f, 0.0f), 0.2f, 0.8f, 0.8f, 10.0f); this._light_ssbo = openGLFactory.NewStorageBuffer(); this._light_ssbo.Create(ref light_source); this._light_ssbo.Bind(2); this._depth_pack_buffer = openGLFactory.NewPixelPackBuffer(); this._depth_pack_buffer.Create <float>(); // states GL.Viewport(0, 0, this._cx, this._cy); //GL.ClearColor(System.Drawing.Color.Beige); GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.CullFace); GL.FrontFace(FrontFaceDirection.Ccw); GL.CullFace(CullFaceMode.Back); // matrices and controller this._view = Matrix4.LookAt(0.0f, -4.0f, 0.0f, 0, 0, 0, 0, 0, 1); float angle = 90.0f * (float)Math.PI / 180.0f; float aspect = (float)this._cx / (float)this._cy; this._projection = Matrix4.CreatePerspectiveFieldOfView(angle, aspect, 0.1f, 100.0f); _controls = new NavigationControls( () => { return(new float[] { 0, 0, (float)this._cx, (float)this._cy }); }, () => { return(this._view); }, () => { return(this._projection); }, this.GetDepth, (cursor_pos) => { return(new Vector3(0, 0, 0)); }, (Matrix4 view) => { this._view = view; } ); }
public void Setup(int cx, int cy) { this._cx = cx; this._cy = cy; // Version strings _version.Retrieve(); // Get OpenGL extensions _extensions.Retrieve(); // Debug callback _debug_callback.Init(); // create Vertex Array Object, Array Buffer Object and Element Array Buffer Object (float[] attributes, uint[] indices) = new Cube().Create(); TVertexFormat[] format = { new TVertexFormat(0, 0, 3, 0, false), new TVertexFormat(0, 1, 3, 3, false), new TVertexFormat(0, 2, 2, 6, false), //new TVertexFormat(0, 2, 4, 8, false), }; _cube_vao = openGLFactory.NewVertexArrayObject(); _cube_vao.AppendVertexBuffer(0, 12, attributes); _cube_vao.Create(format, indices); _cube_vao.Bind(); // Create textures objects _tbos = new List <ITexture>(); _tbos.Add(openGLFactory.NewTexture()); _tbos[0].Create2D(_image_cx, _image_cy, ITexture.Format.RGBA_8); _tbos.Add(openGLFactory.NewTexture()); _tbos[1].Create2D(_image_cx, _image_cy, ITexture.Format.RGBA_F32); _tbos.Add(openGLFactory.NewTexture()); _tbos[2].Create2D(_image_cx, _image_cy, ITexture.Format.RGBA_F32); GL.TextureParameter(_tbos[2].Object, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TextureParameter(_tbos[2].Object, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); // Create generators this._generators = new List <TextureGenerator>(); this._generators.Add(new TextureGenerator(openGLFactory, TextureGenerator.TType.texture_test1, new ITexture[] { _tbos[0] })); this._generators.Add(new TextureGenerator(openGLFactory, TextureGenerator.TType.heightmap_test1, new ITexture[] { _tbos[1] })); this._generators.Add(new TextureGenerator(openGLFactory, TextureGenerator.TType.cone_step_map, new ITexture[] { _tbos[2] }, new ITexture[] { _tbos[1] })); // Create textures foreach (var generator in this._generators) { generator.Generate(); } // Create shader program string vert_shader = @"#version 460 core layout (location = 0) in vec3 inPos; layout (location = 1) in vec3 inNV; layout (location = 2) in vec2 inUV; out TVertexData { vec3 pos; vec3 nv; vec2 uv; float clip; } out_data; layout(std430, binding = 1) buffer MVP { mat4 proj; mat4 view; mat4 model; } mvp; layout(location=1) uniform vec4 u_clipPlane; void main() { vec3 modelNV = mat3( mvp.model ) * normalize( inNV ); out_data.nv = mat3( mvp.view ) * modelNV; out_data.uv = inUV; vec4 worldPos = mvp.model * vec4( inPos, 1.0 ); vec4 viewPos = mvp.view * worldPos; out_data.pos = viewPos.xyz / viewPos.w; gl_Position = mvp.proj * viewPos; vec4 clipPlane = vec4(normalize(u_clipPlane.xyz), u_clipPlane.w); out_data.clip = dot(worldPos, clipPlane); }"; string frag_shader = @"#version 460 core //#define NORMAL_MAP_TEXTURE #define NORMAL_MAP_QUALITY 1 in TVertexData { vec3 pos; vec3 nv; vec2 uv; float clip; } in_data; out vec4 fragColor; layout(std430, binding = 1) buffer MVP { mat4 proj; mat4 view; mat4 model; } mvp; layout(location=1) uniform vec4 u_clipPlane; layout(std430, binding = 2) buffer TLight { vec4 u_lightDir; float u_ambient; float u_diffuse; float u_specular; float u_shininess; } light_data; layout(binding=1) uniform sampler2D u_texture; layout(binding=2) uniform sampler2D u_displacement_map; layout(location=2) uniform float u_displacement_scale; layout(location=3) uniform vec2 u_parallax_quality; #if defined(NORMAL_MAP_TEXTURE) uniform sampler2D u_normal_map; #endif vec2 GetHeightAndCone( in vec2 texCoords ) { vec2 h_and_c = texture( u_displacement_map, texCoords ).rg; return clamp( h_and_c, 0.0, 1.0 ); } vec4 CalculateNormal( in vec2 texCoords ) { #if defined(NORMAL_MAP_TEXTURE) float height = GetHeight( texCoords ); vec3 tempNV = texture( u_normal_map, texCoords ).xyz * 2.0 / 1.0; return vec4( normalize( tempNV ), height ); #else vec2 texOffs = 1.0 / textureSize( u_displacement_map, 0 ).xy; vec2 scale = 1.0 / texOffs; #if NORMAL_MAP_QUALITY > 1 float hx[9]; hx[0] = texture( u_displacement_map, texCoords.st + texOffs * vec2(-1.0, -1.0) ).r; hx[1] = texture( u_displacement_map, texCoords.st + texOffs * vec2( 0.0, -1.0) ).r; hx[2] = texture( u_displacement_map, texCoords.st + texOffs * vec2( 1.0, -1.0) ).r; hx[3] = texture( u_displacement_map, texCoords.st + texOffs * vec2(-1.0, 0.0) ).r; hx[4] = texture( u_displacement_map, texCoords.st ).r; hx[5] = texture( u_displacement_map, texCoords.st + texOffs * vec2( 1.0, 0.0) ).r; hx[6] = texture( u_displacement_map, texCoords.st + texOffs * vec2(-1.0, 1.0) ).r; hx[7] = texture( u_displacement_map, texCoords.st + texOffs * vec2( 0.0, 1.0) ).r; hx[8] = texture( u_displacement_map, texCoords.st + texOffs * vec2( 1.0, 1.0) ).r; vec2 deltaH = vec2(hx[0]-hx[2] + 2.0*(hx[3]-hx[5]) + hx[6]-hx[8], hx[0]-hx[6] + 2.0*(hx[1]-hx[7]) + hx[2]-hx[8]); float h_mid = hx[4]; #elif NORMAL_MAP_QUALITY > 0 float h_mid = texture( u_displacement_map, texCoords.st ).r; float h_xa = texture( u_displacement_map, texCoords.st + texOffs * vec2(-1.0, 0.0) ).r; float h_xb = texture( u_displacement_map, texCoords.st + texOffs * vec2( 1.0, 0.0) ).r; float h_ya = texture( u_displacement_map, texCoords.st + texOffs * vec2( 0.0, -1.0) ).r; float h_yb = texture( u_displacement_map, texCoords.st + texOffs * vec2( 0.0, 1.0) ).r; vec2 deltaH = vec2(h_xa-h_xb, h_ya-h_yb); #else vec4 heights = textureGather( u_displacement_map, texCoords, 0 ); vec2 deltaH = vec2(dot(heights, vec4(1.0, -1.0, -1.0, 1.0)), dot(heights, vec4(-1.0, -1.0, 1.0, 1.0))); float h_mid = heights.w; #endif return vec4( normalize( vec3( deltaH * scale, 1.0 ) ), h_mid ); #endif } // the super fast version // (change number of iterations at run time) float intersect_cone_fixed(in vec2 dp, in vec3 ds) { // the 'not Z' component of the direction vector // (requires that the vector ds was normalized!) float iz = sqrt(1.0 - ds.z * ds.z); // my starting location (is at z=1, // and moving down so I don't have // to invert height maps) // texture lookup (and initialized to starting location) vec4 t; // scaling distance along vector ds float sc; // the ds.z component is positive! // (headed the wrong way, since // I'm using heightmaps) // find the initial location and height t = texture(u_displacement_map, dp); // right, I need to take one step. // I use the current height above the texture, // and the information about the cone-ratio // to size a single step. So it is fast and // precise! (like a coneified version of // 'space leaping', but adapted from voxels) sc = (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); // and repeat a few (4x) times t = texture(u_displacement_map, dp + ds.xy * sc); sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); t = texture(u_displacement_map, dp + ds.xy * sc); sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); t = texture(u_displacement_map, dp + ds.xy * sc); sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); t = texture(u_displacement_map, dp + ds.xy * sc); sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); // and another five! t = texture(u_displacement_map, dp + ds.xy * sc); sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); t = texture(u_displacement_map, dp + ds.xy * sc); sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); t = texture(u_displacement_map, dp + ds.xy * sc); sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); t = texture(u_displacement_map, dp + ds.xy * sc); sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); t = texture(u_displacement_map, dp + ds.xy * sc); sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); // return the vector length needed to hit the height-map return (sc); } // (and you can do LOD by changing 'conesteps' based on size/distance, etc.) float intersect_cone_loop(in vec2 dp, in vec3 ds) { float maxBumpHeight = u_displacement_scale; const int conesteps = 10; // ??? // the 'not Z' component of the direction vector // (requires that the vector ds was normalized!) float iz = sqrt(1.0 - ds.z * ds.z); // my starting location (is at z=1, // and moving down so I don't have // to invert height maps) // texture lookup (and initialized to starting location) vec4 t; // scaling distance along vector ds float sc = 0.0; //t=texture2D(stepmap,dp); //return (max(0.0,-(t.b-0.5)*ds.x-(t.a-0.5)*ds.y)); // the ds.z component is positive! // (headed the wrong way, since // I'm using heightmaps) // adaptive (same speed as it averages the same # steps) //for (int i = int(float(conesteps)*(0.5+iz)); i > 0; --i) // fixed for (int i = conesteps; i > 0; --i) { // find the new location and height t = texture(u_displacement_map, dp + ds.xy * sc); t.r = t.r * maxBumpHeight; t.g = t.g / maxBumpHeight; // right, I need to take one step. // I use the current height above the texture, // and the information about the cone-ratio // to size a single step. So it is fast and // precise! (like a coneified version of // 'space leaping', but adapted from voxels) sc += (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); } // return the vector length needed to hit the height-map return (sc); } // slowest, but best quality float intersect_cone_exact(in vec2 dp, in vec3 ds) { vec2 texsize = textureSize(u_displacement_map, 0); // minimum feature size parameter float w = 1.0 / max(texsize.x, texsize.y); // the 'not Z' component of the direction vector // (requires that the vector ds was normalized!) float iz = sqrt(1.0 - ds.z * ds.z); // my starting location (is at z=1, // and moving down so I don't have // to invert height maps) // texture lookup vec4 t; // scaling distance along vector ds float sc = 0.0; // the ds.z component is positive! // (headed the wrong way, since // I'm using heightmaps) // find the starting location and height t = texture(u_displacement_map, dp); while (1.0 - ds.z * sc > t.r) { // right, I need to take one step. // I use the current height above the texture, // and the information about the cone-ratio // to size a single step. So it is fast and // precise! (like a coneified version of // 'space leaping', but adapted from voxels) sc += w + (1.0 - ds.z * sc - t.r) / (ds.z + iz / (t.g * t.g)); // find the new location and height t = texture(u_displacement_map, dp + ds.xy * sc); } // back off one step sc -= w; // return the vector length needed to hit the height-map return (sc); } // Parallax Occlusion Mapping in GLSL [http://sunandblackcat.com/tipFullView.php?topicid=28] vec3 ConeStep(in float frontFace, in vec3 texDir3D, in vec2 texCoord) { float maxBumpHeight = 1.0; vec2 quality_range = u_parallax_quality; // [Determinante](https://de.wikipedia.org/wiki/Determinante) // A x B = A.x * B.y - A.y * B.x = dot(A, vec2(B.y,-B.x)) = det(mat2(A,B)) // [How do you detect where two line segments intersect?](https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect) vec2 R = normalize(vec2(length(texDir3D.xy), texDir3D.z)); vec2 P = R * maxBumpHeight / texDir3D.z; vec2 tex_size = textureSize(u_displacement_map, 0).xy; vec2 min_tex_step = normalize(texDir3D.xy) / tex_size; float min_step = length(min_tex_step) * 1.0 / R.x; float t = 0.0; const int max_no_of_steps = int(5.0 + quality_range * 45.0); for (int i = 0; i < max_no_of_steps; ++i) { vec3 sample_pt = vec3(texCoord.xy, maxBumpHeight) + texDir3D * t; vec2 h_and_c = GetHeightAndCone(sample_pt.xy); float h = h_and_c.x * maxBumpHeight; float c = h_and_c.y * h_and_c.y / maxBumpHeight; vec2 C = P + R * t; if (C.y <= h) break; vec2 Q = vec2(C.x, h); vec2 S = normalize(vec2(c, 1.0)); float new_t = dot(Q - P, vec2(S.y, -S.x)) / dot(R, vec2(S.y, -S.x)); t = max(t + min_step, new_t); } vec2 texC = texCoord.xy + texDir3D.xy * t; float mapHeight = GetHeightAndCone(texC.xy).x - step(frontFace, 0.0); return vec3(texC.xy, mapHeight); } void main() { vec3 objPosEs = in_data.pos; vec3 objNormalEs = in_data.nv; vec2 texCoords = in_data.uv.st; float frontFace = gl_FrontFacing ? 1.0 : -1.0; // TODO $$$ sign(dot(N,objPosEs)); //vec3 normalEs = frontFace * normalize( objNormalEs ); // orthonormal tangent space matrix //vec3 p_dx = dFdx( objPosEs ); //vec3 p_dy = dFdy( objPosEs ); //vec2 tc_dx = dFdx( texCoords ); //vec2 tc_dy = dFdy( texCoords ); //float texDet = determinant( mat2( tc_dx, tc_dy ) ); //vec3 tangentVec = ( tc_dy.y * p_dx - tc_dx.y * p_dy ) / abs( texDet ); //vec3 tangentEs = normalize( tangentVec - normalEs * dot(tangentVec, normalEs ) ); //mat3 tbnMat = mat3( sign( texDet ) * tangentEs, cross( normalEs, tangentEs ), normalEs ); // Followup: Normal Mapping Without Precomputed Tangents [http://www.thetenthplanet.de/archives/1180] vec3 N = frontFace * normalize(objNormalEs); vec3 dp1 = dFdx(objPosEs); vec3 dp2 = dFdy(objPosEs); vec2 duv1 = dFdx(texCoords); vec2 duv2 = dFdy(texCoords); vec3 dp2perp = cross(dp2, N); vec3 dp1perp = cross(N, dp1); vec3 T = dp2perp * duv1.x + dp1perp * duv2.x; vec3 B = dp2perp * duv1.y + dp1perp * duv2.y; float invmax = inversesqrt(max(dot(T, T), dot(B, B))); mat3 tbnMat = mat3(T * invmax, B * invmax, N * u_displacement_scale); mat3 inv_tbnMat = inverse(tbnMat); vec3 texDir3D = normalize(inv_tbnMat * objPosEs); vec3 newTexCoords = abs(u_displacement_scale) < 0.001 ? vec3(texCoords.st, 0.0) : ConeStep(frontFace, texDir3D, texCoords.st); //float depth_displ = length(tbnMat * (newTexCoords.z * texDir3D.xyz / abs(texDir3D.z))); //vec3 view_pos_displ = objPosEs - depth_displ * normalize(objPosEs); vec3 displ_vec = tbnMat * (newTexCoords.z * texDir3D.xyz / abs(texDir3D.z)); vec3 view_pos_displ = objPosEs - displ_vec; vec4 modelPos = inverse(mvp.view) * vec4(view_pos_displ, 1.0); vec4 clipPlane = vec4(normalize(u_clipPlane.xyz), u_clipPlane.w); float clip_dist = dot(modelPos, clipPlane); //float clip_dist = in_data.clip; if (clip_dist < 0.0) discard; texCoords.st = newTexCoords.xy; vec4 normalVec = CalculateNormal(texCoords); //vec3 nvMappedEs = normalize( tbnMat * normalVec.xyz ); vec3 nvMappedEs = u_displacement_scale < 0.001 ? normalize(objNormalEs) : (normalize(transpose(inv_tbnMat) * normalVec.xyz)); //vec3 color = in_data.col; vec3 color = texture(u_texture, texCoords.st).rgb; // ambient part vec3 lightCol = light_data.u_ambient * color; // diffuse part vec3 normalV = normalize(nvMappedEs); vec3 lightV = -normalize(mat3(mvp.view) * light_data.u_lightDir.xyz); float NdotL = max(0.0, dot(normalV, lightV)); lightCol += NdotL * light_data.u_diffuse * color; // specular part vec3 eyeV = normalize(-objPosEs); vec3 halfV = normalize(eyeV + lightV); float NdotH = max(0.0, dot(normalV, halfV)); float kSpecular = (light_data.u_shininess + 2.0) * pow(NdotH, light_data.u_shininess) / (2.0 * 3.14159265); lightCol += kSpecular * light_data.u_specular * color; fragColor = vec4(lightCol.rgb, 1.0); vec4 proj_pos_displ = mvp.proj * vec4(view_pos_displ.xyz, 1.0); float depth = 0.5 + 0.5 * proj_pos_displ.z / proj_pos_displ.w; gl_FragDepth = u_displacement_scale < 0.001 ? gl_FragCoord.z : depth; //fragColor = vec4( vec3(1.0-depth), 1.0 ); }"; this._parallax_prog = openGLFactory.VertexAndFragmentShaderProgram(vert_shader, frag_shader); this._parallax_prog.Generate(); // Model view projection shader storage block objects and buffers TMVP mvp = new TMVP(Matrix4.Identity, Matrix4.Identity, Matrix4.Identity); this._mvp_ssbo = openGLFactory.NewStorageBuffer(); this._mvp_ssbo.Create(ref mvp); this._mvp_ssbo.Bind(1); TLightSource light_source = new TLightSource(new Vector4(-1.0f, -0.5f, -2.0f, 0.0f), 0.2f, 0.8f, 0.8f, 10.0f); this._light_ssbo = openGLFactory.NewStorageBuffer(); this._light_ssbo.Create(ref light_source); this._light_ssbo.Bind(2); // states GL.Viewport(0, 0, this._cx, this._cy); //GL.ClearColor(System.Drawing.Color.Beige); GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f); GL.Enable(EnableCap.DepthTest); // no face culling, because of clipping //GL.Enable(EnableCap.CullFace); GL.FrontFace(FrontFaceDirection.Ccw); GL.CullFace(CullFaceMode.Back); // matrices and controller this._view = Matrix4.LookAt(0.0f, 0.0f, 2.5f, 0, 0, 0, 0, 1, 0); float angle = 90.0f * (float)Math.PI / 180.0f; float aspect = (float)this._cx / (float)this._cy; this._projection = Matrix4.CreatePerspectiveFieldOfView(angle, aspect, 0.1f, 100.0f); this._spin = new ModelSpinningControls( () => { return(this._period); }, () => { return(new float[] { 0, 0, (float)this._cx, (float)this._cy }); }, () => { return(this._view); } ); this._spin.SetAttenuation(1.0f, 0.05f, 0.0f); // properties ViewModel.HeightScale = 50; ViewModel.QualityScale = 50; ViewModel.ClipScale = 50; }
public void Setup(int cx, int cy) { this._cx = cx; this._cy = cy; // Version strings _version.Retrieve(); // Get OpenGL extensions _extensions.Retrieve(); // Debug callback _debug_callback.Init(); // create Vertex Array Object, Array Buffer Object and Element Array Buffer Object (float[] attributes, uint[] indices) = new Cube().Create(); TVertexFormat[] format = { new TVertexFormat(0, 0, 3, 0, false), new TVertexFormat(0, 1, 3, 3, false), new TVertexFormat(0, 2, 2, 6, false), //new TVertexFormat(0, 2, 4, 8, false), }; _cube_vao = openGLFactory.NewVertexArrayObject(); _cube_vao.AppendVertexBuffer(0, 12, attributes); _cube_vao.Create(format, indices); _cube_vao.Bind(); // Create textures Assembly assembly = Assembly.GetExecutingAssembly(); //string[] names = assembly.GetManifestResourceNames(); Stream textue_stream = assembly.GetManifestResourceStream("OpenTK_parallax_relief_mapping.Resource.woodtiles.jpg"); Stream normalmap_stream = assembly.GetManifestResourceStream("OpenTK_parallax_relief_mapping.Resource.toy_box_normal.png"); Stream displacementmap_stream = assembly.GetManifestResourceStream("OpenTK_parallax_relief_mapping.Resource.toy_box_disp.png"); _texture = openGLFactory.NewTexture(); _texture.Create2D(new Bitmap(textue_stream)); _normalmap = openGLFactory.NewTexture(); _normalmap.Create2D(new Bitmap(normalmap_stream)); _displacementmap = openGLFactory.NewTexture(); _displacementmap.Create2D(new Bitmap(displacementmap_stream)); // Create shader program string vert_shader = @"#version 460 core layout (location = 0) in vec4 a_pos; layout (location = 1) in vec3 a_nv; layout (location = 2) in vec2 a_uv; layout (location = 0) out TVertexData { vec3 w_pos; vec3 w_nv; vec2 uv; vec3 eye_pos; } outData; layout(std430, binding = 1) buffer MVP { mat4 proj; mat4 view; mat4 model; } mvp; void main() { mat3 normal_mat = inverse(transpose(mat3(mvp.model))); outData.w_nv = normalize(normal_mat * a_nv); outData.uv = a_uv; vec4 worldPos = mvp.model * a_pos; outData.w_pos = worldPos.xyz / worldPos.w; outData.eye_pos = inverse(mvp.view)[3].xyz; gl_Position = mvp.proj * mvp.view * mvp.model * a_pos; }"; string frag_shader = @"#version 460 core out vec4 frag_color; layout (location = 0) in TVertexData { vec3 w_pos; vec3 w_nv; vec2 uv; vec3 eye_pos; } inData; layout(std430, binding = 2) buffer TLight { vec4 u_lightDir; float u_ambient; float u_diffuse; float u_specular; float u_shininess; } light_data; layout(binding=1) uniform sampler2D u_diffuse; layout(binding=2) uniform sampler2D u_normal_map; layout(binding=3) uniform sampler2D u_displacement_map; layout(location=1) uniform float u_height_scale; vec2 ParallaxMapping (vec2 texCoord, vec3 viewDir) { float numLayers = 32.0 - 31.0 * abs(dot(vec3(0.0, 0.0, 1.0), viewDir)); float layerDepth = 1.0 / numLayers; vec2 P = viewDir.xy / viewDir.z * u_height_scale; vec2 deltaTexCoords = P / numLayers; vec2 currentTexCoords = texCoord; float currentLayerDepth = 0.0; float currentDepthMapValue = texture2D(u_displacement_map, currentTexCoords).r; for (int i=0; i<32; ++ i) { if (currentLayerDepth >= currentDepthMapValue) break; currentTexCoords -= deltaTexCoords; currentDepthMapValue = texture2D(u_displacement_map, currentTexCoords).r; currentLayerDepth += layerDepth; } vec2 prevTexCoords = currentTexCoords + deltaTexCoords; float afterDepth = currentDepthMapValue - currentLayerDepth; float beforeDepth = texture2D(u_displacement_map, prevTexCoords).r - currentLayerDepth + layerDepth; float weight = afterDepth / (afterDepth - beforeDepth); return prevTexCoords * weight + currentTexCoords * (1.0 - weight); } void main() { vec3 N = normalize(inData.w_nv); vec3 dp1 = dFdx( inData.w_pos ); vec3 dp2 = dFdy( inData.w_pos ); vec2 duv1 = dFdx( inData.uv ); vec2 duv2 = dFdy( inData.uv ); vec3 dp2perp = cross(dp2, N); vec3 dp1perp = cross(N, dp1); vec3 T = dp2perp * duv1.x + dp1perp * duv2.x; vec3 B = dp2perp * duv1.y + dp1perp * duv2.y; float invmax = inversesqrt(max(dot(T, T), dot(B, B))); mat3 tm = mat3(T * invmax, B * invmax, N); mat3 tbn_inv = mat3(vec3(tm[0].x, tm[1].x, tm[2].x), vec3(tm[0].y, tm[1].y, tm[2].y), vec3(tm[0].z, tm[1].z, tm[2].z)); vec3 view_dir = tbn_inv * normalize(inData.w_pos - inData.eye_pos); vec2 uv = ParallaxMapping(inData.uv, view_dir); if (uv.x > 1.0 || uv.y > 1.0 || uv.x < 0.0 || uv.y < 0.0) discard; vec4 color = texture(u_diffuse, uv.xy); vec3 normalV = texture2D(u_normal_map, uv.st).xyz * 2.0 - 1.0; normalV = normalize(vec3(normalV.xy, normalV.z / max(0.001, 10.0 * u_height_scale))); // ambient part vec3 lightCol = light_data.u_ambient * color.rgb; vec3 eyeV = normalize(inData.eye_pos - inData.w_pos); vec3 lightV = tbn_inv * normalize( -light_data.u_lightDir.xyz ); // diffuse part float NdotL = max( 0.0, dot( normalV, lightV ) ); lightCol += NdotL * light_data.u_diffuse * color.rgb; // specular part vec3 halfV = normalize( eyeV + lightV ); float NdotH = max( 0.0, dot( normalV, halfV ) ); float kSpecular = ( light_data.u_shininess + 2.0 ) * pow( NdotH, light_data.u_shininess ) / ( 2.0 * 3.14159265 ); lightCol += kSpecular * light_data.u_specular * color.rgb; frag_color = vec4( lightCol.rgb, color.a ); }"; this._parallax_prog = openGLFactory.VertexAndFragmentShaderProgram(vert_shader, frag_shader); this._parallax_prog.Generate(); // Model view projection shader storage block objects and buffers TMVP mvp = new TMVP(Matrix4.Identity, Matrix4.Identity, Matrix4.Identity); this._mvp_ssbo = openGLFactory.NewStorageBuffer(); this._mvp_ssbo.Create(ref mvp); this._mvp_ssbo.Bind(1); TLightSource light_source = new TLightSource(new Vector4(-1.0f, -0.5f, -2.0f, 0.0f), 0.2f, 0.8f, 0.8f, 10.0f); this._light_ssbo = openGLFactory.NewStorageBuffer(); this._light_ssbo.Create(ref light_source); this._light_ssbo.Bind(2); // states GL.Viewport(0, 0, this._cx, this._cy); //GL.ClearColor(System.Drawing.Color.Beige); GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.CullFace); GL.FrontFace(FrontFaceDirection.Ccw); GL.CullFace(CullFaceMode.Back); // matrices and controller this._view = Matrix4.LookAt(0.0f, 0.0f, 3.0f, 0, 0, 0, 0, 1, 0); float angle = 90.0f * (float)Math.PI / 180.0f; float aspect = (float)this._cx / (float)this._cy; this._projection = Matrix4.CreatePerspectiveFieldOfView(angle, aspect, 0.1f, 100.0f); this._spin = new ModelSpinningControls( () => { return(this._period); }, () => { return(new float[] { 0, 0, (float)this._cx, (float)this._cy }); }, () => { return(this._view); } ); this._spin.SetAttenuation(1.0f, 0.05f, 0.0f); // properties ViewModel.HeightScale = 100; }
//! On load window (once) protected override void OnLoad() { _version = openGLFactory.NewVersionInformation(Console.WriteLine); _extensions = openGLFactory.NewExtensionInformation(); _debug_callback = openGLFactory.NewDebugCallback(Console.WriteLine); // Version strings _version.Retrieve(); // Get OpenGL extensions _extensions.Retrieve(); // Debug callback _debug_callback.Init(); // create Vertex Array Object, Array Buffer Object and Element Array Buffer Object float[] vquad = { // x y z r g b a -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f }; uint [] iquad = { 0, 1, 2, 0, 2, 3 }; TVertexFormat[] format = { new TVertexFormat(0, 0, 3, 0, false), new TVertexFormat(0, 1, 4, 3, false), }; _test_vao = openGLFactory.NewVertexArrayObject(); _test_vao.AppendVertexBuffer(0, 7, vquad); _test_vao.Create(format, iquad); // Create shader program string vert_shader = @"#version 460 core layout (location = 0) in vec4 a_pos; layout (location = 1) in vec4 a_color; out vec4 v_color; uniform mat4 u_transform; void main() { v_color = a_color; gl_Position = u_transform * a_pos; }"; string frag_shader = @"#version 460 core out vec4 frag_color; in vec4 v_color; void main() { frag_color = v_color; }"; this._test_prog = openGLFactory.VertexAndFragmentShaderProgram(vert_shader, frag_shader); this._test_prog.Generate(); this._test_prog.Use(); // states GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f); base.OnLoad(); }
//! On load window (once) protected override void OnLoad() { _version = openGLFactory.NewVersionInformation(Console.WriteLine); _extensions = openGLFactory.NewExtensionInformation(); _debug_callback = openGLFactory.NewDebugCallback(Console.WriteLine); // Version strings _version.Retrieve(); // Get OpenGL extensions _extensions.Retrieve(); // Debug callback _debug_callback.Init(); // create Vertex Array Object, Array Buffer Object and Element Array Buffer Object (float[] attributes, uint[] indices) = new TrefoilKnot(256, 16).Create(); TVertexFormat[] format = { new TVertexFormat(0, 0, 3, 0, false), new TVertexFormat(0, 1, 3, 3, false), //new TVertexFormat(0, ?, 2, 6, false), new TVertexFormat(0, 2, 4, 8, false), }; _test_vao = openGLFactory.NewVertexArrayObject(); _test_vao.AppendVertexBuffer(0, 12, attributes); _test_vao.Create(format, indices); _test_vao.Bind(); // Create shader program string vert_shader = @"#version 460 core layout (location = 0) in vec4 a_pos; layout (location = 1) in vec3 a_nv; layout (location = 2) in vec4 a_color; layout (location = 0) out TVertexData { vec3 pos; vec3 nv; vec4 col; } outData; layout(std430, binding = 1) buffer MVP { mat4 proj; mat4 view; mat4 model; } mvp; void main() { mat4 mv_mat = mvp.view * mvp.model; mat3 normal_mat = inverse(transpose(mat3(mv_mat))); outData.nv = normalize(normal_mat * a_nv); outData.col = a_color; vec4 viewPos = mv_mat * a_pos; outData.pos = viewPos.xyz / viewPos.w; gl_Position = mvp.proj * viewPos; }"; string frag_shader = @"#version 460 core out vec4 frag_color; layout (location = 0) in TVertexData { vec3 pos; vec3 nv; vec4 col; } inData; layout(std430, binding = 2) buffer TLight { vec4 u_lightDir; float u_ambient; float u_diffuse; float u_specular; float u_shininess; } light_data; void main() { vec3 color = inData.col.rgb; // ambient part vec3 lightCol = light_data.u_ambient * color; vec3 normalV = normalize( inData.nv ); vec3 eyeV = normalize( -inData.pos ); vec3 lightV = normalize( -light_data.u_lightDir.xyz ); // diffuse part float NdotL = max( 0.0, dot( normalV, lightV ) ); lightCol += NdotL * light_data.u_diffuse * color; // specular part vec3 halfV = normalize( eyeV + lightV ); float NdotH = max( 0.0, dot( normalV, halfV ) ); float kSpecular = ( light_data.u_shininess + 2.0 ) * pow( NdotH, light_data.u_shininess ) / ( 2.0 * 3.14159265 ); lightCol += kSpecular * light_data.u_specular * color; frag_color = vec4( lightCol.rgb, inData.col.a ); }"; this._test_prog = openGLFactory.VertexAndFragmentShaderProgram(vert_shader, frag_shader); this._test_prog.Generate(); // Model view projection shader storage block objects and buffers TMVP mvp = new TMVP(Matrix4.Identity, Matrix4.Identity, Matrix4.Identity); this._mvp_ssbo = openGLFactory.NewStorageBuffer(); this._mvp_ssbo.Create(ref mvp); this._mvp_ssbo.Bind(1); TLightSource light_source = new TLightSource(new Vector4(-1.0f, -0.5f, -2.0f, 0.0f), 0.2f, 0.8f, 0.8f, 10.0f); this._light_ssbo = openGLFactory.NewStorageBuffer(); this._light_ssbo.Create(ref light_source); this._light_ssbo.Bind(2); // states GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.CullFace); GL.FrontFace(FrontFaceDirection.Ccw); GL.CullFace(CullFaceMode.Back); // matrices and controller this._view = Matrix4.LookAt(0.0f, 0.0f, 1.5f, 0, 0, 0, 0, 1, 0); var spin = new ModelSpinningControls( () => { return(this._period); }, () => { return(new float[] { 0, 0, (float)this.Size.X, (float)this.Size.Y }); }, () => { return(this._view); } ); spin.SetAttenuation(1.0f, 0.05f, 0.0f); this._controls = spin; base.OnLoad(); }
//! On load window (once) protected override void OnLoad() { _version = openGLFactory.NewVersionInformation(Console.WriteLine); _extensions = openGLFactory.NewExtensionInformation(); _debug_callback = openGLFactory.NewDebugCallback(Console.WriteLine); // Version strings _version.Retrieve(); // Get OpenGL extensions _extensions.Retrieve(); // Debug callback _debug_callback.Init(); // create Vertex Array Object, Array Buffer Object and Element Array Buffer Object float[] vquad = { // x y z u v -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f }; uint[] iquad = { 0, 1, 2, 0, 2, 3 }; TVertexFormat[] format = { new TVertexFormat(0, 0, 3, 0, false), new TVertexFormat(0, 1, 2, 3, false), }; _test_vao = openGLFactory.NewVertexArrayObject(); _test_vao.AppendVertexBuffer(0, 5, vquad); _test_vao.Create(format, iquad); // Create texture Assembly assembly = Assembly.GetExecutingAssembly(); string[] names = assembly.GetManifestResourceNames(); Stream resource_stream = assembly.GetManifestResourceStream("OpenTK_example_3.Resource.background.jpg"); _test_texture = openGLFactory.NewTexture(); _test_texture.Create2D(new Bitmap(resource_stream)); // Create shader program string vert_shader = @"#version 460 core layout (location = 0) in vec4 a_pos; layout (location = 1) in vec2 a_uv; out vec2 v_uv; void main() { v_uv = a_uv; gl_Position = a_pos; }"; string frag_shader = @"#version 460 core out vec4 frag_color; in vec2 v_uv; layout(binding = 7) uniform sampler2D u_texture; void main() { frag_color = texture(u_texture, v_uv).rgba; }"; this._test_prog = openGLFactory.VertexAndFragmentShaderProgram(vert_shader, frag_shader); this._test_prog.Generate(); this._test_prog.Use(); // states GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f); base.OnLoad(); }