packages feed

immutaball-core-0.1.0.4.1: Immutaball/Share/Video/Shaders.hs

{-# OPTIONS_GHC -fno-warn-tabs #-}  -- Support tab indentation better, for a better default of no warning if tabs are used: https://dmitryfrank.com/articles/indent_with_tabs_align_with_spaces .
-- Enable warnings:
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

-- CLI.hs.

{-# LANGUAGE Haskell2010 #-}

module Immutaball.Share.Video.Shaders
	(
		vertexShader,
		fragmentShader
	) where

import Prelude ()
import Immutaball.Prelude

vertexShader :: String
vertexShader = unlines $
	[
		"#version 450 core",
		"",
		"layout(location = 0) in vec3 position;",
		"layout(location = 1) in vec4 modulateColor;",
		"layout(location = 2) in vec2 texCoords;",
		"layout(location = 3) in int  texLayer;",
		"layout(location = 4) in int  elem;",
		"",
		"out      vec4 vertexModulateColor;",
		"out      vec2 vertexTexCoords;",
		"out flat int  vertexTexLayer;",
		"out flat int  doDiscard;",
		"",
		"// 3 modes: drawing GUI (false, false) drawing scene / level (true, false), and drawing ball (false, true)",
		"layout(location = 16) uniform int   enableSceneData;",
		"layout(location = 34) uniform int   enableBallData;",
		"layout(location = 35) uniform float ballRadius;",
		"layout(location = 36) uniform int   ballNumTriangles;",
		"layout(location = 37) uniform vec3  ballPos;",
		"layout(location = 38) uniform vec3  ballRot;",
		"",
		"// 16 SOL render analysis arrays (scene data), locations 17-32",
		"layout(std430, binding = 17) buffer layoutSSBOVertexData {",
		--"\tdouble ssboVertexData[];",
		"\t float ssboVertexData[];",
		"};",
		"layout(std430, binding = 18) buffer layoutSSBOGeomData {",
		"\tint ssboGeomData[];",
		"};",
		"layout(std430, binding = 19) buffer layoutSSBOLumpData {",
		"\tint ssboLumpData[];",
		"};",
		"layout(std430, binding = 20) buffer layoutSSBOPathDoublesData {",
		--"\tdouble ssboPathDoublesData[];",
		"\t float ssboPathDoublesData[];",
		"};",
		"layout(std430, binding = 21) buffer layoutSSBOPathInt32sData {",
		"\tint ssboPathInt32sData[];",
		"};",
		"layout(std430, binding = 22) buffer layoutSSBOBodyData {",
		"\tint ssboBodyData[];",
		"};",
		"layout(std430, binding = 23) buffer layoutSSBOGcData {",
		"\tint ssboGcData[];",
		"};",
		"layout(std430, binding = 24) buffer layoutSSBOAllGeomPassMvData {",
		"\tint ssboAllGeomPassMvData[];",
		"};",
		"layout(std430, binding = 25) buffer layoutSSBOAllGeomPassTexturesData {",
		"\tint ssboAllGeomPassTexturesData[];",
		"};",
		"layout(std430, binding = 26) buffer layoutSSBOAllGeomPassGisData {",
		"\tint ssboAllGeomPassGisData[];",
		"};",
		"layout(std430, binding = 27) buffer layoutSSBOGeomPassMvRangesData {",
		"\tint ssboGeomPassMvRangesData[];",
		"};",
		"layout(std430, binding = 28) buffer layoutSSBOGeomPassTexturesRangesData {",
		"\tint ssboGeomPassTexturesRangesData[];",
		"};",
		"layout(std430, binding = 29) buffer layoutSSBOGeomPassGisRangesData {",
		"\tint ssboGeomPassGisRangesData[];",
		"};",
		"layout(std430, binding = 30) buffer layoutSSBOGeomPassBisData {",
		"\tint ssboGeomPassBisData[];",
		"};",
		"",
		"layout(std430, binding = 31) buffer layoutSSBOTransformationData {",
		--"\tdouble ssboTransformationData[];",
		"\t float ssboTransformationData[];",
		"};",
		"",
		"layout(std430, binding = 32) buffer layoutSSBOTexcoordsDoubleData {",
		--"\tdouble ssboTexcoordsDoubleData[];",
		"\t float ssboTexcoordsDoubleData[];",
		"};",
		"",
		"layout(location = 33) uniform int sceneGeomPassIdx;",
		"",
		"// Required for linking with GL_PROGRAM_SEPARABLE apparently.",
		"out gl_PerVertex {",
		"\tvec4  gl_Position;",
		"\tfloat gl_PointSize;",
		"\tfloat gl_ClipDistance[];",
		"};",
		"",
		--"vec4 rowMajorMatMulVecdf(double mat[16], vec4 untransformed) {",
		"vec4 rowMajorMatMulVecdf( float mat[16], vec4 untransformed) {",
		"\tfloat transformedx = float(mat[0]) * untransformed.x + float(mat[1]) * untransformed.y + float(mat[2]) * untransformed.z + float(mat[3]) * untransformed.w;",
		"\tfloat transformedy = float(mat[4]) * untransformed.x + float(mat[5]) * untransformed.y + float(mat[6]) * untransformed.z + float(mat[7]) * untransformed.w;",
		"\tfloat transformedz = float(mat[8]) * untransformed.x + float(mat[9]) * untransformed.y + float(mat[10]) * untransformed.z + float(mat[11]) * untransformed.w;",
		"\tfloat transformedw = float(mat[12]) * untransformed.x + float(mat[13]) * untransformed.y + float(mat[14]) * untransformed.z + float(mat[15]) * untransformed.w;",
		"\treturn vec4(transformedx, transformedy, transformedz, transformedw);",
		"}",
		"",
		"vec4 transfMul(vec4 untransformed) {",
		"\t//vec4 transformed = rowMajorMatMulVecdf(ssboTransformationData, untransformed);",
		"\tfloat transformedx = float(ssboTransformationData[0]) * untransformed.x + float(ssboTransformationData[1]) * untransformed.y + float(ssboTransformationData[2]) * untransformed.z + float(ssboTransformationData[3]) * untransformed.w;",
		"\tfloat transformedy = float(ssboTransformationData[4]) * untransformed.x + float(ssboTransformationData[5]) * untransformed.y + float(ssboTransformationData[6]) * untransformed.z + float(ssboTransformationData[7]) * untransformed.w;",
		"\tfloat transformedz = float(ssboTransformationData[8]) * untransformed.x + float(ssboTransformationData[9]) * untransformed.y + float(ssboTransformationData[10]) * untransformed.z + float(ssboTransformationData[11]) * untransformed.w;",
		"\tfloat transformedw = float(ssboTransformationData[12]) * untransformed.x + float(ssboTransformationData[13]) * untransformed.y + float(ssboTransformationData[14]) * untransformed.z + float(ssboTransformationData[15]) * untransformed.w;",
		"\tvec4 transformed = vec4(transformedx, transformedy, transformedz, transformedw);",
		"\treturn transformed;",
		"}",
		"",
		"void mainGUI() {",
		"\tgl_Position = vec4(position, 1.0);",
		"\tvertexModulateColor = modulateColor;",
		"\tvertexTexCoords = texCoords;",
		"\tvertexTexLayer = texLayer;",
		"\tdoDiscard = 0;",
		"}",
		"",
		"void mainScene() {",
		"\t// Render elem ‘elem’ in the geom pass ‘sceneGeomPassIdx’.",
		"\tint geomPassTexture0 = ssboGeomPassTexturesRangesData[2*sceneGeomPassIdx+0];",
		"\tint geomPassTexturec = ssboGeomPassTexturesRangesData[2*sceneGeomPassIdx+1];",
		"\tint geomPassGi0      = ssboGeomPassGisRangesData[2*sceneGeomPassIdx+0];",
		"\tint geomPassGic      = ssboGeomPassGisRangesData[2*sceneGeomPassIdx+1];",
		"",
		"\tint whichElem = elem / 3;",
		"\tint whichVert = elem % 3;",
		"",
		"\tint texture = ssboAllGeomPassTexturesData[( geomPassTexture0 + whichElem )];",
		"\tint gi      = ssboAllGeomPassGisData[(      geomPassGi0      + whichElem )];",
		"",
		"\tint vi = ssboGeomData[9*gi+0];",
		"\tint vj = ssboGeomData[9*gi+1];",
		"\tint vk = ssboGeomData[9*gi+2];",
		"\tint ti = ssboGeomData[9*gi+3];",
		"\tint tj = ssboGeomData[9*gi+4];",
		"\tint tk = ssboGeomData[9*gi+5];",
		"\tint si = ssboGeomData[9*gi+6];",
		"\tint sj = ssboGeomData[9*gi+7];",
		"\tint sk = ssboGeomData[9*gi+8];",
		"",
		"\tint v = ssboGeomData[9*gi+0+(whichVert)];",
		"\tint t = ssboGeomData[9*gi+3+(whichVert)];",
		"\tint s = ssboGeomData[9*gi+6+(whichVert)];",
		"",
		"\t// Texture coords.",
		--"\tdouble texs  = ssboTexcoordsDoubleData[2*t+0];",
		--"\tdouble text  = ssboTexcoordsDoubleData[2*t+1];",
		"\t float texs  = ssboTexcoordsDoubleData[2*t+0];",
		"\t float text  = ssboTexcoordsDoubleData[2*t+1];",
		"\tfloat  texsf = float(texs);",
		"\tfloat  textf = float(text);",
		"",
		--"\tdouble vx = ssboVertexData[3*v+0];",
		--"\tdouble vy = ssboVertexData[3*v+1];",
		--"\tdouble vz = ssboVertexData[3*v+2];",
		"\t float vx = ssboVertexData[3*v+0];",
		"\t float vy = ssboVertexData[3*v+1];",
		"\t float vz = ssboVertexData[3*v+2];",
		"\tfloat vxf = float(vx);",
		"\tfloat vyf = float(vy);",
		"\tfloat vzf = float(vz);",
		"\tvec3 vfbase = vec3(vxf, vyf, vzf);",
		"\tvec4 vfuntransformed = vec4(vfbase, 1.0);",
		"\tvec4 vf = transfMul(vfuntransformed);",
		"\tvec4 out_gl_Position = vf;",
		-- TODO DEBUG
		--"\tout_gl_Position = (!(gi > 50)) ? vf : (whichVert==0?vec4(vf.x,0.0,0.0,1.0):(whichVert==1?vec4(0.0,1.0,0.0,1.0):vec4(1.0,1.0,0.0,1.0)));",
		"",
		"\tvec4 out_modulateColor = vec4(1.0, 1.0, 1.0, 1.0);",
		"",
		"\tvec2 out_texCoords = vec2(texsf, textf);",
		"",
		"\tint out_texLayer = texture;",
		"",
		"\tgl_Position = out_gl_Position;",
		--"\tgl_Position = whichVert==0?vec4(vf.x,0.0,0.0,1.0):(whichVert==1?vec4(0.0,1.0,0.0,1.0):vec4(1.0,1.0,0.0,1.0));",  -- TODO DEBUG
		--"\tgl_Position = vfuntransformed;",  -- TODO DEBUG
		--"\tgl_Position = (sceneGeomPassIdx%3)==0?vec4(0.0,0.0,0.0,1.0):((sceneGeomPassIdx%3)==1?vec4(0.0,1.0,0.0,1.0):vec4(1.0,1.0,0.0,1.0));",  -- TODO DEBUG
		"\tvertexModulateColor = out_modulateColor;",
		"\tvertexTexCoords = out_texCoords;",
		"\tvertexTexLayer = out_texLayer;",
		"\tdoDiscard = 0;",
		"}",
		"",
		"// glDrawArrays is called with ballNumTriangles * 3, and elem is vertex to render.",
		"void mainBall() {",
		"\tint whichElem = elem / 3;",
		"\tint whichVert = elem % 3;  // Which of the 3 vertices of the triangle?",
		"",
		"\t// Now partition into squares and then triangles; consecutive",
		"\t// triangle pairs represent which of the 2 triangles of the square",
		"\t// to use.",
		--"\tint whichDivision = whichElem / 2;",
		--"\tint whichTriPart = whichElem % 2;  // First triangle or second triangle of the square?",
		"\tint whichSquare = whichElem / 2;",
		"\tint whichSquareTri = whichElem % 2;  // First triangle or second triangle of the square?",
		"",
		"\t// Make a circle on xy plane, then repeat with the xy plane tilted",
		"\t// until the tilt makes a full circle.",
		"\t// The number of circles equals the number of tilts.",
		"\tint squaresInOneCircle = int(round(sqrt(float(ballNumTriangles / 2)) - 0.6));",
		"\tint numTilts           = squaresInOneCircle;",
		"",
		"\t// 4 points for 2 triangles: inner p0, inner p1, outer p0, outer p1",
		"\t// (outer is 1 tilt further than inner, p1 is one sample in the circle",
		"\t// further than p0).",
		"\tint whichSquarePoint = whichVert + whichSquareTri;",
		"\tbool sp0 = whichSquarePoint == 0;",
		"\tbool sp1 = whichSquarePoint == 1;",
		"\tbool sp2 = whichSquarePoint == 2;",
		"\tbool sp3 = whichSquarePoint == 3;",
		"",
		"\tint onNextSample = (sp1 || sp3) ? 1 : 0;  // Is this point p1 and not p0?  (Advance the sample / partition index within the tilt by 1.)",
		"\tint onNextTilt   = (sp2 || sp3) ? 1 : 0;  // Is this point on the next tilt, rather than the current?",
		"",
		"\tconst float pi  = radians(180);",
		"\tconst float tau = radians(360);",
		"",
		"\tint whichCircleSample  = whichSquare % numTilts           + onNextSample;",
		"\tint whichTilt          = whichSquare / squaresInOneCircle + onNextTilt;",
		"\tfloat circleSample     = float(whichCircleSample) / float(squaresInOneCircle);  // 0.0 represents the start of the circle; 1.0 represents 360 degrees.",
		"\tfloat tilt             = float(whichTilt)         / float(numTilts);            // 0.0 represents the first tilt; 1.0 represents all tilts are done.",
		"\tfloat circleSampleRad_ = tau*circleSample;  // In radians.",
		"\tfloat tiltRad_         = tau*tilt;          // In radians.",
		"",
		"\tfloat circleSampleRad  = circleSampleRad_ + ballRot.z;  // rotatexy (aim right) - first transformation",
		"\tfloat spinRad          =                    ballRot.y;  // second transformation - only handles ball rotation about y axis.",
		"\tfloat tiltRad          = tiltRad_         + ballRot.x;  // rotateyz (aim down) - third transformation",
		"",
		"\t// Now calculate the raw vertex based on circleSample and tilt, all 3 axis rotations in fact, starting at radius 1 before we scale and apply pos and rot.",
		"\t// For the math, one way is to compose 3 rotatexx matrices.",
		"\t// rotateyz tiltRad <> rotatexz spinRad <> rotatexy circleSampleRad =",
		"\t//          (rotxy)",
		"\t//          c   s   0",
		"\t//          -s  c   0",
		"\t//          0   0   1",
		"\t// (rxz)",
		"\t// C  0  S  Cc  Cs  S",
		"\t// 0  1  0  -s  c   0",
		"\t// -S 0  C  -Sc -Ss C …",
		"",
		"\t//          (…)",
		"\t//          Cc  Cs  S",
		"\t//          -s  c   0",
		"\t//          -Sc -Ss C",
		"\t// (ryz)",
		"\t// 1  0  0  Cc  Cs  S",
		"\t// 0  č  š  (-čs-šSc) ( čc-šSs) (šC)",
		"\t// 0  -š č  ( šs-čSc) (-šc-čSs) (čC)",
		"\t//",
		"\t// Multiply the resulting matrix by the starting point 1,0,0 to get the raw position.",
		"\t// vec3 rawVertPos = Cc, -čs-šSc, šs-čSc",
		"\tfloat angleszc = cos(circleSampleRad);",
		"\tfloat angleszs = sin(circleSampleRad);",
		"\tfloat anglesyc = cos(spinRad);",
		"\tfloat anglesys = sin(spinRad);",
		"\tfloat anglesxc = cos(tiltRad);",
		"\tfloat anglesxs = sin(tiltRad);",
		"\tvec3 rawVertPos = vec3(anglesyc * angleszc, -anglesxc*angleszs-anglesxs*anglesys*angleszc, anglesxs*angleszs-anglesxc*anglesys*angleszc);",
		--"\tvec3 rawVertPosDebugMonolith = vec3(circleSampleRad, 0.0, tiltRad);  // Can be used for debugging purposes to see a monolith 2D ball.",
		"\tvec3 vertPos = ballPos + ballRadius*rawVertPos;",
		"\t// Apply the global transformation.",
		"\tvec4 glVertPos = transfMul(vec4(vertPos, 1.0));",
		"",
		"\tbool blackNotWhite = int(round(4*circleSample)) % 2 == int(round(4*tilt)) % 2;",
		"\tvec4 ballTriangleColor = blackNotWhite ? vec4(0.0, 0.0, 0.0, 0.8) : vec4(1.0, 1.0, 1.0, 0.8);",
		"",
		"\t// Write output.",
		"\tgl_Position = glVertPos;",
		"\tvertexModulateColor = ballTriangleColor;",
		"\tvertexTexCoords = vec2(0.0, 0.0);  // Fragment shader will ignore.",
		"\tvertexTexLayer = 0;  // Fragment shader will ignore.",
		"\tdoDiscard = 0;",
		"}",
		"",
		"void mainUnknown() {",
		"\tgl_Position = vec4(0.0, 0.0, 0.0, 1.0);",
		"\tvertexModulateColor = vec4(0.0, 0.0, 0.0, 0.0);",
		"\tvertexTexCoords = vec2(0.0, 0.0);",
		"\tvertexTexLayer = 0;",
		"\tdoDiscard = 1;",
		"}",
		"",
		"void main() {",
		"\tif (!(enableSceneData != 0) && !(enableBallData != 0)) {",
		"\t\tmainGUI();",
		"\t} else if ((enableSceneData != 0) && !(enableBallData != 0)) {",
		"\t\tmainScene();",
		"\t} else if (!(enableSceneData != 0) && (enableBallData != 0)) {",
		"\t\tmainBall();",
		"\t} else {",
		"\t\t// Unknown configuration / shader mode; unknown what to draw.",
		"\t\tmainUnknown();",
		"\t}",
		"}",
		"",
		""
	]

fragmentShader :: String
fragmentShader = unlines $
	[
		"#version 450 core",
		"",
		"in  vec4  gl_FragCoord;",
		"out vec4  fragmentColor;",
		"out float gl_FragDepth;",
		"",
		"in      vec4 vertexModulateColor;",
		"in      vec2 vertexTexCoords;",
		"in flat int  vertexTexLayer;",
		"in flat int  doDiscard;",
		"",
		"layout(location = 16) uniform int       enableSceneData;",
		"layout(location = 34) uniform int       enableBallData;",
		"layout(location = 35) uniform float     ballRadius;",
		"layout(location = 36) uniform int       ballNumTriangles;",
		"layout(location = 37) uniform vec3      ballPos;",
		"layout(location = 38) uniform vec3      ballRot;",
		"",
		"layout(location =  0) uniform sampler2D texture0;",
		"layout(location =  1) uniform sampler2D texture1;",
		"layout(location =  2) uniform sampler2D texture2;",
		"layout(location =  3) uniform sampler2D texture3;",
		"layout(location =  4) uniform sampler2D texture4;",
		"layout(location =  5) uniform sampler2D texture5;",
		"layout(location =  6) uniform sampler2D texture6;",
		"layout(location =  7) uniform sampler2D texture7;",
		"layout(location =  8) uniform sampler2D texture8;",
		"layout(location =  9) uniform sampler2D texture9;",
		"layout(location = 10) uniform sampler2D texture10;",
		"layout(location = 11) uniform sampler2D texture11;",
		"layout(location = 12) uniform sampler2D texture12;",
		"layout(location = 13) uniform sampler2D texture13;",
		"layout(location = 14) uniform sampler2D texture14;",
		"layout(location = 15) uniform sampler2D texture15;",
		"",
		"\t// Draw the GUI or the level.",
		"void mainGUIOrScene() {",
		"\tgl_FragDepth = 1.0e-6 * gl_FragCoord.z/gl_FragCoord.w;",
		"\tfragmentColor = ",
		"\t\tvertexTexLayer ==  0 ? texture(texture0,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer ==  1 ? texture(texture1,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer ==  2 ? texture(texture2,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer ==  3 ? texture(texture3,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer ==  4 ? texture(texture4,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer ==  5 ? texture(texture5,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer ==  6 ? texture(texture6,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer ==  7 ? texture(texture7,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer ==  8 ? texture(texture8,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer ==  9 ? texture(texture9,  vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer == 10 ? texture(texture10, vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer == 11 ? texture(texture11, vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer == 12 ? texture(texture12, vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer == 13 ? texture(texture13, vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer == 14 ? texture(texture14, vertexTexCoords) * vertexModulateColor :",
		"\t\tvertexTexLayer == 15 ? texture(texture15, vertexTexCoords) * vertexModulateColor :",
		"\t\tvec4(0.0, 0.0, 0.0, 0.0);",
		"}",
		"",
		"\t// Draw the ball.",
		"void mainBall() {",
		"\tgl_FragDepth = 1.0e-6 * gl_FragCoord.z/gl_FragCoord.w;",
		"\tfragmentColor = vertexModulateColor;",
		"}",
		"",
		"void main() {",
		--"\tfragmentColor = texture(texture0, vertexTexCoords);",
		"\tif ((doDiscard != 0)) {",
		"\t\tdiscard;",
		"\t} else if (!(enableSceneData != 0) && (enableBallData != 0)) {",
		"\t\tmainBall();",
		"\t} else {",
		"\t\tmainGUIOrScene();",
		"\t}",
		"}",
		"",
		""
	]