Refactor ShaderProgram class for improved readability and structure; add missing imports. Minor HTML formatting adjustments in index.html.
This commit is contained in:
@@ -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); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user