複数の異なるテクスチャを表示するようにコードをリファクタリングする前は、すべてが正常に機能していましたが、現在は、サイズが想定よりも小さいブラックボックスしかなく、明らかにテクスチャがありません。頂点にも触れませんでした。サイズが影響を受ける理由はまったくありません。
スクリーンショット(黒い大きなボックスが画面全体を覆い、下部の小さな正方形がはるかに大きくなっているはずです。サイズに影響したものがわからない):シェーダー:(使用前にコンパイルされます)
const val vertexShader_Image = "uniform mat4 u_MVPMatrix;" +
"attribute vec4 a_Position;" +
"attribute vec2 a_texCoord;" +
"varying vec2 v_texCoord;" +
"void main() {" +
" gl_Position = u_MVPMatrix * a_Position;" +
" v_texCoord = a_texCoord;" +
"}"
const val fragmentShader_Image = "precision mediump float;" +
"uniform sampler2D u_texture;" +
"varying vec2 v_texCoord;" +
"void main() {" +
" gl_FragColor = texture2D(u_texture, v_texCoord);" +
"}"
TextureLoader :(オブジェクトは基本的にKotlinの静的クラスです(慣れていない場合))
object TextureLoader
{
var textures: Map<TextureName, Int> = mutableMapOf()
fun generateTextures(nameBitmapPair: List<Pair<TextureName, Bitmap>>, screenWidth: Int, screenHeight: Int)
{
val textureAmount = nameBitmapPair.size
val mutableTextureMap = mutableMapOf<TextureName, Int>()
if(textureAmount > 31 || textureAmount< 0)
{
throw IllegalStateException("Texture amount is bigger than 31 or smaller than 0. Texture limit for OPEN GL is 31, it can't be bigger than it")
}
val textureHandles = IntArray(textureAmount)
GLES20.glGenTextures(textureAmount, textureHandles, 0)
for (i in 0 until textureAmount)
{
if (textureHandles[i] != 0)
{
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandles[i])
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR)
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, nameBitmapPair.get(i).second, 0)
nameBitmapPair.get(i).second.recycle()
mutableTextureMap.put(nameBitmapPair.get(i).first, textureHandles[i])
Timber.i("created new texture, Name = ${nameBitmapPair.get(i).first}, ID = ${textureHandles[i]}")
}
else
{
throw RuntimeException("Error loading texture.")
}
}
textures = mutableTextureMap
}
}
Batcher: (The class that handles the OpenGL boilerplate code so the rest of the codebase doesn't bleed anyone's eyes)
class Batcher private constructor()
{
// Store the model matrix. This matrix is used to move models from object space (where each model can be thought
// of being located at the center of the universe) to world space.
private val mtrxModel = FloatArray(16)
// Allocate storage for the final combined matrix. This will be passed into the shader program.
private val mtrxMVP = FloatArray(16)
// Store the projection matrix. This is used to project the scene onto a 2D viewport.
private val mtrxProjection = FloatArray(16)
/* This was my UV array before I refactored the code to add animations. Now it's accessed by the
sprite.animator.getUvCoordinationForCurrentFrame()
private var uvArray = floatArrayOf(
0.0f, 0.0f,
0.0f, 0.20f,
0.20f, 0.20f,
0.20f, 0.0f)
*/
private var uvBuffer: FloatBuffer? = null
private var vertexBuffer: FloatBuffer? = null
private var indices = shortArrayOf(0, 1, 2, 0, 2, 3) // The order of vertexrendering.
private var indicesBuffer: ShortBuffer? = null
// NOTE: companion object is the static class of the Kotlin if you are not familiar with it. It's used to create a singleton here.
companion object
{
private var instance: Batcher? = null
fun getInstance(): Batcher
{
if (instance == null)
{
instance = Batcher()
}
return instance!!
}
}
//Constructor of the Kotlin classes if you aren't familiar with it
init
{
glEnable(GL_BLEND)
// initialize byte buffer for the draw list
indicesBuffer = ByteBuffer.allocateDirect(indices.size * 2)
.order(ByteOrder.nativeOrder())
.asShortBuffer()
indicesBuffer!!.put(indices)
.position(0)
val vertices = floatArrayOf(
0f, 0f, 0f,
0f, 1.0f, 0f,
1.0f, 1.0f, 0f,
1.0f, 0f, 0f)
// The vertex buffer.
vertexBuffer = ByteBuffer.allocateDirect(vertices.size * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
vertexBuffer!!.put(vertices)
.position(0)
}
fun render(sprites: Sprites)
{
//TODO should these be called on every draw call??
// Get handle to shape's transformation matrix
val u_MVPMatrix = glGetUniformLocation(ShaderHelper.programTexture, "u_MVPMatrix")
val a_Position = glGetAttribLocation(ShaderHelper.programTexture, "a_Position")
val a_texCoord = glGetAttribLocation(ShaderHelper.programTexture, "a_texCoord")
val u_texture = glGetUniformLocation(ShaderHelper.programTexture, "u_texture")
glEnableVertexAttribArray(a_Position)
glEnableVertexAttribArray(a_texCoord)
// "it" here is the currently iterated sprite object
sprites.forEach{
val uvArray = it.animator.getUvCoordinationForCurrentFrame()
if (uvArray != null)
{
updateUVBuffer(uvArray)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
// Matrix op - start
Matrix.setIdentityM(mtrxMVP, 0)
Matrix.setIdentityM(mtrxModel, 0)
Matrix.translateM(mtrxModel, 0, it.x.toFloat(), it.y.toFloat(), 0f)
Matrix.scaleM(mtrxModel, 0, it.scaledFrameWidth.toFloat(), it.scaledFrameHeight.toFloat(), 0f)
if (it.isHorizontallyFlipped)
{
Matrix.translateM(mtrxModel, 0, 1f, 0f, 0f)
Matrix.scaleM(mtrxModel, 0, -1f, 1f, 0f)
}
Matrix.multiplyMM(mtrxMVP, 0, mtrxModel, 0, mtrxMVP, 0)
Matrix.multiplyMM(mtrxMVP, 0, mtrxProjection, 0, mtrxMVP, 0)
// Matrix op - end
// Pass the data to shaders - start
// Prepare the triangle coordinate data
//Binds this vertex's data to a spot in the buffer
glVertexAttribPointer(a_Position, 3, GL_FLOAT, false, 0, vertexBuffer)
// Prepare the texture coordinates
glVertexAttribPointer(a_texCoord, 2, GL_FLOAT, false, 0, uvBuffer)
glUniformMatrix4fv(u_MVPMatrix, 1, false, mtrxMVP, 0)
// Set the sampler texture unit to where we have saved the texture.
// second param is the active texture index
glUniform1i(u_texture, TextureLoader.textures.get(it.textureName)!!)
// Draw the triangles
glDrawElements(GL_TRIANGLES, indices.size, GL_UNSIGNED_SHORT, indicesBuffer)
}
else
{
Timber.w("UV array of the sprite is null, skipping rendering. \nSprite: ${it}")
}
}
}
fun setScreenDimension(screenWidth: Int, screenHeight: Int)
{
Matrix.setIdentityM(mtrxProjection, 0)
Matrix.orthoM(mtrxProjection, 0, 0f, screenWidth.toFloat(), screenHeight.toFloat(), 0f, 0f, 1f)
}
private fun updateUVBuffer(uvArray: FloatArray)
{
uvBuffer = ByteBuffer.allocateDirect(uvArray.size * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
uvBuffer!!.put(uvArray)
.position(0)
}
The value to be assigned to the texture sampler uniform is not the object number of the texture. It must be the texture unit that the texture is bound to. Since your texture is bound to texture unit 0 (GL_TEXTURE0
), you need to assign 0 to the texture sampler uniform (0 is default):
glUniform1i(u_texture, TextureLoader.textures.get(it.textureName)!!)
glUniform1i(u_texture, 0)
glBindTexture
binds a texture to the specified target and the current texture unit. The texture unit can be set by glActiveTexture
.
If you do
glActiveTexture(GLES20.GL_TEXTURE0)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandles[i])
then you have to assign 0 to the texture sampler. But if you do
glActiveTexture(GLES20.GL_TEXTURE1)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandles[i])
then you have to assign 1 to the texture sampler.
メッシュを描画する前に、テクスチャがバインドされていることを確認する必要があります。テクスチャが異なるため、テクスチャglBindTexture
を使用してジオメトリをレンダリングするたびに呼び出す必要があります。例:
glActiveTexture(GLES20.GL_TEXTURE0)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, TextureLoader.textures.get(it.textureName)!!)
glUniform1i(u_texture, 0)
glDrawElements(GL_TRIANGLES, indices.size, GL_UNSIGNED_SHORT, indicesBuffer)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加