質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

Q&A

解決済

1回答

1925閲覧

OpenTKを使用したシャドウマッピングの実装が上手く動かない

Rei_312

総合スコア24

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

0グッド

0クリップ

投稿2022/04/10 07:35

前提

OpenTKとC#を使用してOpenGLの勉強をしています。
こちらのサイト(https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping)を参考にしながらシャドウマッピングを実装しようとしているのですが、このサイトでは、C/C++を使用して説明されているので、C#とOpenTKの仕様に合わせて書き換える必要があると思います。
自分で以下のコードを書いたのですが、うまく動きません。
どなたか間違えている箇所を指摘していただきたいです。

該当のソースコード

C#

1 2private int _depthMapFramebuffer = -1; 3private int _depthMapTexture = -1; 4void ShadowMap( Vector3 lightPosition, Vector3 lightTarget, Action drawFunction, Action<ShaderProgram> shaderSetting ) 5{ 6 const int shadowWidth = 1024; 7 const int shadowHeight = 1024; 8 9 //フレームバッファが生成されていなかったら生成する 10 if ( _depthMapFramebuffer == -1 ) 11 { 12 _depthMapFramebuffer = GL.GenFramebuffer(); 13 } 14 15 //テクスチャが生成されていなかったら生成してフレームバッファに設定 16 if ( _depthMapTexture == -1 ) 17 { 18 _depthMapTexture = GL.GenTexture(); 19 GL.BindTexture( TextureTarget.Texture2D, _depthMapTexture ); 20 GL.TexImage2D( TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent, shadowWidth, shadowHeight, 0, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero ); 21 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); 22 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); 23 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); 24 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); 25 26 GL.BindFramebuffer( FramebufferTarget.Framebuffer, _depthMapFramebuffer ); 27 GL.FramebufferTexture2D( FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, TextureTarget.Texture2D, _depthMapTexture, 0 ); 28 GL.DrawBuffer(DrawBufferMode.None); 29 GL.ReadBuffer(ReadBufferMode.None); 30 GL.BindFramebuffer( FramebufferTarget.Framebuffer, 0 ); 31 GL.BindTexture( TextureTarget.Texture2D, 0 ); 32 } 33 34 //フレームバッファをバインドしてビューポートを深度マップのサイズに変更 35 GL.BindFramebuffer( FramebufferTarget.Framebuffer, _depthMapFramebuffer ); 36 GL.Viewport( 0, 0, shadowWidth, shadowHeight ); 37 //深度バッファをクリア 38 GL.Clear( ClearBufferMask.DepthBufferBit ); 39 40 //正射影の射影行列を作成 41 float near = 0.5f, far = 1200f; 42 Matrix4 projection = Matrix4.CreateOrthographicOffCenter( -Window.Width / 2, Window.Width / 2, -Window.Height / 2, Window.Height / 2, near, far ); 43 //ビュー行列を作成 44 Matrix4 view = Matrix4.LookAt( lightPosition, lightTarget, new Vector3( 0, 1, 0 ) ); 45 46 47 depthMapShader.Use(); 48 //行列を転置してシェーダーに渡す 49 depthMapShader.SetUniform( "lightView", true, view ); 50 depthMapShader.SetUniform( "lightProj", true, projection ); 51 52 //深度マップに描画 53 drawFunction(); 54 55 //フレームバッファのバインドを解除してビューポートをもとに戻す 56 GL.BindFramebuffer( FramebufferTarget.Framebuffer, 0 ); 57 GL.Viewport( 0, 0, Window.Width, Window.Height ); 58 59 shadowLightingShader.Use(); 60 //行列を転置してシェーダーに渡す 61 shadowLightingShader.SetUniform( "lightView", true, view ); 62 shadowLightingShader.SetUniform( "lightProj", true, projection ); 63 64 //通常の行列をシェーダーにわたす 65 SendMatricesToShader(); 66 67 //深度マップをバインド 68 GL.ActiveTexture( TextureUnit.Texture1 ); 69 GL.BindTexture( TextureTarget.Texture2D, _depthMapTexture ); 70 71 //テクスチャの位置を渡す 72 shadowLightingShader.SetUniform( "shadowMap", 1 ); 73 74 //シェーダーの設定をする関数を呼び出す 75 shaderSetting( shadowLightingShader ); 76 77 //描画 78 drawFunction(); 79 80 //テクスチャのバインドを解除 81 GL.BindTexture(TextureTarget.Texture2D, 0); 82 GL.ActiveTexture(TextureUnit.Texture0); 83}

深度マップに書き込むシェーダー(depthMapShader):

バーテックスシェーダー:

GLSL

1#version 430 2 3layout ( location = 0 ) uniform mat4 modelMatrix; 4layout ( location = 1 ) uniform mat4 viewMatrix; 5layout ( location = 2 ) uniform mat4 projMatrix; 6layout ( location = 3 ) uniform mat4 lightView; 7layout ( location = 4 ) uniform mat4 lightProj; 8 9layout ( location = 0 ) in vec3 position; 10 11void main() 12{ 13 //行列の乗算の順序を反転 14 gl_Position = vec4(position, 1.0) * modelMatrix * lightView * lightProj; 15}

フラグメントシェーダー:

GLSL

1#version 430 2 3void main() 4{ 5 //何も書かなくて良い 6}

ライティングと影の処理をするシェーダー(shadowLightingShader):
バーテックスシェーダー:

GLSL

1#version 430 2precision mediump float; 3 4layout ( location = 0 ) uniform mat4 modelMatrix; 5layout ( location = 1 ) uniform mat4 viewMatrix; 6layout ( location = 2 ) uniform mat4 projMatrix; 7layout ( location = 3 ) uniform mat4 lightView; 8layout ( location = 4 ) uniform mat4 lightProj; 9 10layout ( location = 0 ) in vec3 position; 11layout ( location = 1 ) in vec4 color; 12layout ( location = 2 ) in vec3 normal; 13layout ( location = 3 ) in vec2 texCoord; 14 15out vec4 vColor; 16out vec3 vFragPosition; 17out vec3 vNormal; 18out vec2 vTexCoord; 19out vec4 vFragPosLightSpace; 20 21void main() 22{ 23 vFragPosition = vec3(vec4(position, 1.0) * modelMatrix); 24 //ライトから見た位置 25 vFragPosLightSpace = vec4(position, 1.0) * modelMatrix * lightView * lightProj; 26 vColor = color; 27 vNormal = normal; 28 vTexCoord = texCoord; 29 gl_Position = vec4(position, 1.0) * modelMatrix * viewMatrix * projMatrix; 30}

フラグメントシェーダー:

GLSL

1#version 430 2precision mediump float; 3 4in vec4 vColor; 5in vec3 vFragPosition; 6in vec3 vNormal; 7in vec2 vTexCoord; 8in vec4 vFragPosLightSpace; 9 10//ライティングに関する設定 11#define MAX_LIGHTS 32; 12uniform int lightCount = MAX_LIGHTS; 13uniform vec3 lightPositions[32]; 14uniform float lightPowers[32]; 15uniform vec3 lightColors[32]; 16uniform float lightRadius[32]; 17uniform float ambientPower; 18uniform vec3 objectColor; 19uniform vec3 ambientColor; 20uniform vec3 emissiveColor; 21uniform vec3 viewPos; 22uniform vec3 directionalColor; 23uniform vec3 directionalDir; 24uniform vec3 directionalPower; 25 26uniform sampler2D shadowMap; //深度マップ 27 28out vec4 fragColor; 29 30//影を計算する関数 31float GetShadow() 32{ 33 vec3 projCoords = vFragPosLightSpace.xyz / vFragPosLightSpace.w; 34 projCoords = projCoords * 0.5 + 0.5; 35 float closestDepth = texture(shadowMap, projCoords.xy).r; 36 float currentDepth = projCoords.z; 37 vec3 normal = normalize(vNormal); 38 float bias = 0.05f; 39 float shadow = 0.0; 40 vec2 texelSize = 1.0 / textureSize(shadowMap, 0); 41 for(int x = -1; x <= 1; ++x) 42 { 43 for(int y = -1; y <= 1; ++y) 44 { 45 float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; 46 shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; 47 } 48 } 49 shadow /= 9.0; 50 if(projCoords.z > 1.0) 51 shadow = 0.0; 52 53 return shadow; 54} 55 56void main() 57{ 58 //ライティング 59 vec3 ambient = ambientPower * ambientColor; 60 61 vec3 totalDiffuse = vec3(0); 62 63 vec3 norm = normalize(vNormal); 64 for ( int i = 0; i < lightCount; i++ ) 65 { 66 float radius = lightRadius[i]; 67 float dist = distance(vFragPosition, lightPositions[i]); 68 float att = clamp(1.0 - dist/radius, 0.0, 1.0); 69 att *= att; 70 float diffuseStrength = lightPowers[i]; 71 vec3 lightDirection = normalize(lightPositions[i] - vFragPosition); 72 float diff = max(dot(norm, lightDirection), 0.0); 73 vec3 diffuse = att * (diffuseStrength * diff) * lightColors[i]; 74 totalDiffuse += diffuse; 75 } 76 77 vec3 didir = normalize(directionalDir); 78 float d = max(dot(norm, didir), 0.0); 79 totalDiffuse += (directionalPower * d) * directionalColor; 80 81 //影を考慮した結果を計算 82 float shadow = GetShadow(); 83 vec3 result = (ambient + (1.0 - shadow) * totalDiffuse) * vColor.rgb + emissiveColor; 84 fragColor = vec4(result, vColor.a); 85}

ShadowMapメソッドの呼び出し:

C#

1//描画ループの中 2 3Action draw = () =>{ 4 //四角形を2つ描画する 5 float[] va = new float[] 6 { 7 -512, 0, -512, 8 -512, 0, -512 + 1024, 9 -512 + 1024, 0, -512, 10 -512 + 1024, 0, -512 + 1024 11 }; 12 13 float[] ca = new float[] 14 { 15 1f, 0f, 0f, 1f, 16 1f, 0f, 0f, 1f, 17 1f, 0f, 0f, 1f, 18 1f, 0f, 0f, 1f, 19 }; 20 21 float[] na = new float[] 22 { 23 0f, 1f, 0f, 24 0f, 1f, 0f, 25 0f, 1f, 0f, 26 0f, 1f, 0f 27 }; 28 29 30 GL.EnableVertexAttribArray(0); 31 GL.EnableVertexAttribArray(1); 32 GL.EnableVertexAttribArray(2); 33 34 GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, va); 35 GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, 0, ca); 36 GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, false, 0, na); 37 38 GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4); 39 40 GL.DisableVertexAttribArray(0); 41 GL.DisableVertexAttribArray(1); 42 GL.DisableVertexAttribArray(2); 43 44 va = new float[] 45 { 46 x, y, z, 47 x, y - height, z, 48 x + width, y, z, 49 x + width, y - height, z 50 }; 51 52 ca = new float[] 53 { 54 1f, 1f, 1f, 1f, 55 1f, 1f, 1f, 1f, 56 1f, 1f, 1f, 1f, 57 1f, 1f, 1f, 1f, 58 }; 59 60 na = new float[] 61 { 62 0f, 0f, 1f, 63 0f, 0f, 1f, 64 0f, 0f, 1f, 65 0f, 0f, 1f, 66 }; 67 68 GL.EnableVertexAttribArray(0); 69 GL.EnableVertexAttribArray(1); 70 GL.EnableVertexAttribArray(2); 71 72 GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, va); 73 GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, 0, ca); 74 GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, false, 0, na); 75 76 GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4); 77 78 GL.DisableVertexAttribArray(0); 79 GL.DisableVertexAttribArray(1); 80 GL.DisableVertexAttribArray(2); 81 82}; 83ShadowMap( _cameraPosition, new Vector3( 0, 0, 0 ), draw, () => {} );

試したこと

参考にしたサイトにあった方法で、深度マップを画面に描画してみたところ、正しい結果が得られているようでした。
イメージ1
イメージ2

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

行列の計算部分にGlmSharpライブラリを使用して行い、uniform変数に設定する際の転置をfalseにすると解決しました。

投稿2022/04/12 08:00

Rei_312

総合スコア24

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問