私は現在、LWJGL 3を使用していて、シンプルなスカイボックスを構築しています。スカイボックスには、等角度マップであるHDRファイルが必要です。 PNGDecoderを使ってPNGで実行しているスカイボックスを取得できますが、HDRファイルでどのように動作するかはわかりません。私が理解しているところでは、STB(C++のように)はHDRファイルをプログラムにアップロードし、LWJGL 3はSTBをサポートします。LWJGLでHDRマップを使用する3
STBとHDRファイルをサポートするloadTexture関数を作成するにはどうすればよいですか?
編集:誰かが私が取り組んでいることを誰もが見ることができるように私は進歩を投稿するつもりです。
マイLoaderクラスはすべて私のloadTexture方法を保持していると私はテクスチャIDを保存するint型の方法を使用していますが、現在の方法は、次のようになります。私はからもらった
public int loadCubeMap(String textureFile) throws IOException { int texID = glGenTextures(); glBindTexture(GL_TEXTURE_2D, texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ByteBuffer imageBuffer; IntBuffer w = BufferUtils.createIntBuffer(1); IntBuffer h = BufferUtils.createIntBuffer(1); IntBuffer comp = BufferUtils.createIntBuffer(1); ByteBuffer image; imageBuffer = IOUtil.ioResourceToByteBuffer(textureFile, 8 * 1024); if (!stbi_info_from_memory(imageBuffer, w, h, comp)) throw new IOException("Failed to read image information: " + stbi_failure_reason()); image = stbi_load_from_memory(imageBuffer, w, h, comp, 3); if (image == null) throw new IOException("Failed to load image: " + stbi_failure_reason()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w.get(0), h.get(0), 0, GL_RGB, GL_UNSIGNED_BYTE, image); stbi_image_free(image); return texID; }
このデモlwjgl3-demos hereには、HDRテクスチャを使用し、STBImage Javaバインディングを使用する環境マップの例があります。またこのメソッドは、サンプルの中で動作しているサンプルのIOUtilという、私のutilsパッケージ内のクラスも使用しています。 (私はまた、私のコードではなく、例でうまくいくlearnOpenglチュートリアルからHDRファイルを試しました)。
私はすべてがうまくいくように見えるスカイボックスシェイダーとスカイボックスレンダラーを持っています。スカイボックスのレンダラは、以下のように書かれている:
パブリッククラスSkyboxRenderer {
private static final float SIZE = 500f;
private static final float[] VERTICES = {
-SIZE, SIZE, -SIZE,
-SIZE, -SIZE, -SIZE,
SIZE, -SIZE, -SIZE,
SIZE, -SIZE, -SIZE,
SIZE, SIZE, -SIZE,
-SIZE, SIZE, -SIZE,
-SIZE, -SIZE, SIZE,
-SIZE, -SIZE, -SIZE,
-SIZE, SIZE, -SIZE,
-SIZE, SIZE, -SIZE,
-SIZE, SIZE, SIZE,
-SIZE, -SIZE, SIZE,
SIZE, -SIZE, -SIZE,
SIZE, -SIZE, SIZE,
SIZE, SIZE, SIZE,
SIZE, SIZE, SIZE,
SIZE, SIZE, -SIZE,
SIZE, -SIZE, -SIZE,
-SIZE, -SIZE, SIZE,
-SIZE, SIZE, SIZE,
SIZE, SIZE, SIZE,
SIZE, SIZE, SIZE,
SIZE, -SIZE, SIZE,
-SIZE, -SIZE, SIZE,
-SIZE, SIZE, -SIZE,
SIZE, SIZE, -SIZE,
SIZE, SIZE, SIZE,
SIZE, SIZE, SIZE,
-SIZE, SIZE, SIZE,
-SIZE, SIZE, -SIZE,
-SIZE, -SIZE, -SIZE,
-SIZE, -SIZE, SIZE,
SIZE, -SIZE, -SIZE,
SIZE, -SIZE, -SIZE,
-SIZE, -SIZE, SIZE,
SIZE, -SIZE, SIZE
};
private RawModel cube;
private int skyboxTexture;
private SkyboxShader shader;
public SkyboxRenderer(Loader loader, Matrix4f projectionMatrix) throws IOException {
cube = loader.loadToVAO(VERTICES, 3);
skyboxTexture = loader.loadCubeMap("res/newport_loft.hdr");
shader = new SkyboxShader();
shader.start();
shader.loadProjectionMatrix(projectionMatrix);
shader.connectTextureUnits();
shader.stop();
}
public void render(Camera camera) {
shader.start();
shader.loadViewMatrix(camera);
GL30.glBindVertexArray(cube.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, skyboxTexture);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, cube.getVertexCount());
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
shader.stop();
}
}
は私がlearnOpenglのPBRのチュートリアルから来た頂点とフラグメントシェーダを使用しています。
頂点シェーダ:
#version 330 core
layout (location = 0) in vec3 aPos;
out vec3 WorldPos;
uniform mat4 projection;
uniform mat4 view;
void main() {
WorldPos = aPos;
gl_Position = projection * view * vec4(WorldPos, 1.0); }
フラグメントシェーダ:シェーダコードがThinmatrixのチュートリアルの助けから、同様にそれがそうであるように動作
#version 330 core
out vec4 FragColor;
in vec3 WorldPos;
uniform sampler2D equirectangularMap;
const vec2 invAtan = vec2(0.1591, 0.3183);
vec2 SampleSphericalMap(vec3 v)
{
vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
uv *= invAtan;
uv += 0.5;
return uv;
}
void main()
{
vec2 uv = SampleSphericalMap(normalize(WorldPos));
vec3 color = texture(equirectangularMap, uv).rgb;
FragColor = vec4(color, 1.0);
}
。
パブリッククラスSkyboxShaderがShaderProgram {
private static final String VERTEX_FILE = "src/skybox/cubemap.vs";
private static final String FRAGMENT_FILE = "src/skybox/cubemap.fs";
private int location_projectionMatrix;
private int location_viewMatrix;
private int location_equirectangularMap;
public SkyboxShader() {
super(VERTEX_FILE, FRAGMENT_FILE);
}
public void loadProjectionMatrix(Matrix4f matrix){
super.loadMatrix(location_projectionMatrix, matrix);
}
public void loadViewMatrix(Camera camera){
Matrix4f matrix = Maths.createViewMatrix(camera);
super.loadMatrix(location_viewMatrix, matrix);
}
@Override
protected void getAllUniformLocations() {
location_projectionMatrix = super.getUniformLocation("projection");
location_viewMatrix = super.getUniformLocation("view");
location_equirectangularMap = super.getUniformLocation("equirectangularMap");
}
@Override
protected void bindAttributes() {
super.bindAttribute(0, "aPos");
}
public void connectTextureUnits() {
super.loadInt(location_equirectangularMap, 0);
} }
を拡張Iは、マスターレンダラークラスのスカイボックスレンダラーの初期化、ファイル名と共にスカイボックスレンダラでloadCubeMap機能を初期化します。
私が実行するまでに、私はHDRテクスチャとローダーについて何の誤りもないので、それを受け入れると仮定します。そのほとんどは動作します。
私はボックスと質感を得るが、テクスチャは、間違ったテクスチャに結合されます。私の地形で使っているアルベド地面の絡み具合は、物事が正しく拘束されていないときのデフォルトの状態であると推測します。
編集:私は、HDRマップが球のために使用されていることに気付き、キューブをレンダリングしています。 (笑)
だから、私は問題を理解していないようです。私はそれに別の渦を吹き込み、私が改善できるものを見ます。どんな助けでも大歓迎です。
編集:
だから私はそれを再加工しようとしました。イメージ変数はFloat Bufferに変更され、stbi_loadf_from_memoryでイメージを受け入れるようになりました。まだ混乱していて、HDRマップがこれを混乱させるとは思わなかった。代わりにあなたがHDRファイルを読み込む機能である、stbi_loadf_from_memory()
を使用する必要がありますstbi_load_from_memory()
の
public int loadCubeMap(String textureFile) throws IOException {
int texID = glGenTextures();
//glActiveTexture(GL11.GL_TEXTURE);
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
ByteBuffer imageBuffer;
IntBuffer w = BufferUtils.createIntBuffer(1);
IntBuffer h = BufferUtils.createIntBuffer(1);
IntBuffer comp = BufferUtils.createIntBuffer(1);
FloatBuffer image;
imageBuffer = IOUtil.ioResourceToByteBuffer(textureFile, 8 * 1024);
if (!stbi_info_from_memory(imageBuffer, w, h, comp))
throw new IOException("Failed to read image information: " + stbi_failure_reason());
image = stbi_loadf_from_memory(imageBuffer, w, h, comp, 3);
if (image == null)
throw new IOException("Failed to load image: " + stbi_failure_reason());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16, w.get(0), h.get(0), 0, GL_RGB16, GL_FLOAT, image);
stbi_image_free(image);
return texID;
お返事ありがとうございます!これまでは、BytebufferイメージをFloatBufferに変更しました。そして、image = stbi_load_from_memoryをstbi_loadf_from_memoryに変更しました。エラーチェックでも同じままで、w、h、およびcomp変数のIntBuffersは同じです。 GL_RGB16Fが見つかりません。ライブラリの現在のバージョンがあります。 – winnieTheWind
また、私は、HDRイメージをロードするように見える例がありますが、stbi_loadfや適切な浮動小数点が必要ではありません。 HDRイメージを最大限に使用したい場合にのみ必要なので、私はそれを前提としています。 – winnieTheWind
(1)GL_RGB16Fは、http://legacy.lwjgl.org/javadoc/org/lwjgl/opengl/GL30.html#GL_RGB16Fを参照してください。(2)HDRは、高ダイナミックレンジのように、通常、浮動小数点値はるかに広い範囲の値を格納することができます。 – sterin