Refactor ShaderProgram class for improved readability and structure; add missing imports. Minor HTML formatting adjustments in index.html.

This commit is contained in:
2025-10-18 13:45:28 +02:00
parent fcabd72075
commit 74fce5d574
2 changed files with 108 additions and 79 deletions

View File

@@ -1,6 +1,10 @@
package com.persesgames.shader package com.persesgames.shader
import org.khronos.webgl.* import org.khronos.webgl.Float32Array
import org.khronos.webgl.WebGLBuffer
import org.khronos.webgl.WebGLProgram
import org.khronos.webgl.WebGLRenderingContext
import org.khronos.webgl.WebGLShader
/** /**
* User: rnentjes * User: rnentjes
@@ -9,8 +13,8 @@ import org.khronos.webgl.*
*/ */
class VertextAttributeInfo(val locationName: String, val numElements: Int) { class VertextAttributeInfo(val locationName: String, val numElements: Int) {
var location = 0 var location = 0
var offset = 0 var offset = 0
} }
class ShaderProgram<T>( class ShaderProgram<T>(
@@ -19,98 +23,122 @@ class ShaderProgram<T>(
vertexShaderSource: String, vertexShaderSource: String,
fragmentShaderSource: String, fragmentShaderSource: String,
val vainfo: Array<VertextAttributeInfo>, val vainfo: Array<VertextAttributeInfo>,
val setter: (program: ShaderProgram<T>, data: T) -> Unit) { val setter: (program: ShaderProgram<T>, data: T) -> Unit
) {
var shaderProgram: WebGLProgram var shaderProgram: WebGLProgram
var vertex: WebGLShader var vertex: WebGLShader
var fragment: WebGLShader var fragment: WebGLShader
var verticesBlockSize = 0 var verticesBlockSize = 0
var drawLength = 0 var drawLength = 0
init { init {
vertex = compileShader(vertexShaderSource, WebGLRenderingContext.VERTEX_SHADER) vertex = compileShader(vertexShaderSource, WebGLRenderingContext.VERTEX_SHADER)
fragment = compileShader(fragmentShaderSource, WebGLRenderingContext.FRAGMENT_SHADER) fragment = compileShader(fragmentShaderSource, WebGLRenderingContext.FRAGMENT_SHADER)
shaderProgram = webgl.createProgram() ?: throw IllegalStateException("Unable to request shader program from webgl context!") shaderProgram = webgl.createProgram()
webgl.attachShader(shaderProgram, vertex) ?: throw IllegalStateException("Unable to request shader program from webgl context!")
webgl.attachShader(shaderProgram, fragment) webgl.attachShader(shaderProgram, vertex)
webgl.linkProgram(shaderProgram) webgl.attachShader(shaderProgram, fragment)
webgl.linkProgram(shaderProgram)
if (webgl.getProgramParameter(shaderProgram, WebGLRenderingContext.LINK_STATUS) == false) { if (webgl.getProgramParameter(shaderProgram, WebGLRenderingContext.LINK_STATUS) == false) {
println(webgl.getProgramInfoLog(shaderProgram)) println(webgl.getProgramInfoLog(shaderProgram))
throw IllegalStateException("Unable to compile shader program!") throw IllegalStateException("Unable to compile shader program!")
}
webgl.useProgram(shaderProgram)
this.verticesBlockSize = 0;
// set attribute locations...
for (info in vainfo.iterator()) {
info.location = webgl.getAttribLocation(shaderProgram, info.locationName)
info.offset = verticesBlockSize;
verticesBlockSize += info.numElements;
println("attrib: ${info.locationName}, info.location: ${info.location}, info.offset: ${info.offset}");
}
when(drawType) {
WebGLRenderingContext.TRIANGLES -> {
drawLength = verticesBlockSize * 3
}
else -> {
drawLength = verticesBlockSize
}
}
println("verticesBlockSize $verticesBlockSize");
println("ShaderProgram constructor done");
} }
private fun compileShader(source: String, type: Int): WebGLShader { webgl.useProgram(shaderProgram)
val result: WebGLShader
result = webgl.createShader(type) ?: throw IllegalStateException("Unable to request shader from webgl context!") this.verticesBlockSize = 0;
webgl.shaderSource(result, source)
webgl.compileShader(result)
if (webgl.getShaderParameter(result, WebGLRenderingContext.COMPILE_STATUS) == false) { // set attribute locations...
throw IllegalStateException("Unable to compile shader!\n${source}\n\n${webgl.getShaderInfoLog(result)}") for (info in vainfo.iterator()) {
} info.location = webgl.getAttribLocation(shaderProgram, info.locationName)
info.offset = verticesBlockSize;
return result; verticesBlockSize += info.numElements;
println("attrib: ${info.locationName}, info.location: ${info.location}, info.offset: ${info.offset}");
} }
fun begin(attribBuffer: WebGLBuffer, userdata: T) { when (drawType) {
webgl.useProgram(shaderProgram); WebGLRenderingContext.TRIANGLES -> {
webgl.bindBuffer(WebGLRenderingContext.ARRAY_BUFFER, attribBuffer); drawLength = verticesBlockSize * 3
}
// set attribute locations... else -> {
for (info in vainfo.iterator()) { drawLength = verticesBlockSize
webgl.enableVertexAttribArray(info.location); }
webgl.vertexAttribPointer(info.location, info.numElements, WebGLRenderingContext.FLOAT, false, verticesBlockSize * 4, info.offset * 4);
}
setter(this, userdata)
} }
fun end() { println("verticesBlockSize $verticesBlockSize");
for (info in vainfo.iterator()) {
webgl.disableVertexAttribArray(info.location); println("ShaderProgram constructor done");
} }
webgl.useProgram(null)
private fun compileShader(source: String, type: Int): WebGLShader {
val result: WebGLShader = webgl.createShader(type)
?: throw IllegalStateException("Unable to request shader from webgl context!")
webgl.shaderSource(result, source)
webgl.compileShader(result)
if (webgl.getShaderParameter(result, WebGLRenderingContext.COMPILE_STATUS) == false) {
throw IllegalStateException(
"Unable to compile shader!\n${source}\n\n${
webgl.getShaderInfoLog(
result
)
}"
)
} }
fun getAttribLocation(location: String) = webgl.getAttribLocation(shaderProgram, location); return result;
}
fun getUniformLocation(location: String) = webgl.getUniformLocation(shaderProgram, location); fun begin(attribBuffer: WebGLBuffer, userdata: T) {
webgl.useProgram(shaderProgram);
webgl.bindBuffer(WebGLRenderingContext.ARRAY_BUFFER, attribBuffer);
fun setUniform1f(location: String, value: Float) { webgl.uniform1f(getUniformLocation(location), value); } // set attribute locations...
fun setUniform2f(location: String, v1: Float, v2: Float) { webgl.uniform2f(getUniformLocation(location), v1, v2); } for (info in vainfo.iterator()) {
fun setUniform4f(location: String, v1: Float, v2: Float, v3: Float, v4: Float) { webgl.uniform4f(getUniformLocation(location), v1, v2, v3, v4); } webgl.enableVertexAttribArray(info.location);
fun setUniform1i(location: String, value: Int) { webgl.uniform1i(getUniformLocation(location), value); } webgl.vertexAttribPointer(
fun setUniformMatrix4fv(location: String, value: Float32Array) { webgl.uniformMatrix4fv(getUniformLocation(location), false, value); } info.location,
info.numElements,
WebGLRenderingContext.FLOAT,
false,
verticesBlockSize * 4,
info.offset * 4
);
}
setter(this, userdata)
}
fun end() {
for (info in vainfo.iterator()) {
webgl.disableVertexAttribArray(info.location);
}
webgl.useProgram(null)
}
fun getAttribLocation(location: String) = webgl.getAttribLocation(shaderProgram, location);
fun getUniformLocation(location: String) = webgl.getUniformLocation(shaderProgram, location);
fun setUniform1f(location: String, value: Float) {
webgl.uniform1f(getUniformLocation(location), value); }
fun setUniform2f(location: String, v1: Float, v2: Float) {
webgl.uniform2f(getUniformLocation(location), v1, v2); }
fun setUniform4f(location: String, v1: Float, v2: Float, v3: Float, v4: Float) {
webgl.uniform4f(getUniformLocation(location), v1, v2, v3, v4); }
fun setUniform1i(location: String, value: Int) {
webgl.uniform1i(getUniformLocation(location), value); }
fun setUniformMatrix4fv(location: String, value: Float32Array) {
webgl.uniformMatrix4fv(getUniformLocation(location), false, value); }
} }

View File

@@ -11,12 +11,13 @@
padding: 0; padding: 0;
overflow: hidden; overflow: hidden;
} }
canvas { canvas {
position:absolute; position: absolute;
} }
</style> </style>
</head> </head>
<body> <body>
<script type="application/javascript" src="fractal.js"></script> <script type="application/javascript" src="fractal.js"></script>
</body> </body>
</html> </html>