Created
May 13, 2018 21:20
-
-
Save lhog/75602b39a2ee3c8e658571dd31d21446 to your computer and use it in GitHub Desktop.
Geometry Shader Instancing in Spring/ZK
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- $Id: gui_metal_features.lua 3171 2008-11-06 09:06:29Z det $ | |
-------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------------- | |
-- | |
-- file: gui_metal_features.lua | |
-- brief: highlights features with metal in metal-map viewmode | |
-- author: Dave Rodgers | |
-- | |
-- Copyright (C) 2007. | |
-- Licensed under the terms of the GNU GPL, v2 or later. | |
-- | |
-------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------------- | |
function widget:GetInfo() | |
return { | |
name = "MetalFeatures", | |
desc = "Highlights features with metal in the metal-map viewmode", | |
author = "trepan", | |
date = "Aug 05, 2007", --May 6, 2013 | |
license = "GNU GPL, v2 or later", | |
layer = 0, | |
enabled = true, -- loaded by default? | |
} | |
end | |
local spGetMapDrawMode = Spring.GetMapDrawMode | |
local spGetActiveCommand = Spring.GetActiveCommand | |
local spGetActiveCmdDesc = Spring.GetActiveCmdDesc | |
-------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------------- | |
local hilite = false | |
local geometryShaderCode = [[ | |
#version 150 compatibility | |
#extension GL_EXT_geometry_shader4 : enable | |
#define MAX_VERTICES _MAX_VERT_ | |
layout(triangles) in; | |
layout(triangle_strip, max_vertices = 1024) out; | |
uniform float transformVector[(3 + 4) * MAX_VERTICES]; | |
uniform int maxObjects; | |
//uniform float alpha; | |
uniform mat4 projMat; | |
uniform mat4 viewMat; | |
//varying mat4 modMat; | |
flat out vec3 rgb; | |
mat4 translationMatrix(in vec3 t) | |
{ | |
return mat4(1.0, 0.0, 0.0, 0.0, | |
0.0, 1.0, 0.0, 0.0, | |
0.0, 0.0, 1.0, 0.0, | |
t.x, t.y, t.z, 1.0); | |
} | |
mat4 scaleMatrix(vec3 s) | |
{ | |
return mat4(s.x, 0.0, 0.0, 0.0, | |
0.0, s.y, 0.0, 0.0, | |
0.0, 0.0, s.z, 0.0, | |
0.0, 0.0, 0.0, 1.0); | |
} | |
mat4 rotationMatrix(vec3 axis, float angle) | |
{ | |
axis = normalize(axis); | |
float s = sin(angle); | |
float c = cos(angle); | |
float oc = 1.0 - c; | |
return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, | |
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, | |
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, | |
0.0, 0.0, 0.0, 1.0); | |
} | |
#define QuarternionConjugate(q) vec4(-q.x, -q.y, -q.z, q.w) | |
vec4 QuarternionFromAxisAngle(vec3 axis, float angle) | |
{ | |
vec4 qr; | |
float half_angle = (angle * 0.5); | |
qr.x = axis.x * sin(half_angle); | |
qr.y = axis.y * sin(half_angle); | |
qr.z = axis.z * sin(half_angle); | |
qr.w = cos(half_angle); | |
return qr; | |
} | |
vec4 QuarternionMult(vec4 q1, vec4 q2) | |
{ | |
vec4 qr; | |
qr.x = (q1.w * q2.x) + (q1.x * q2.w) + (q1.y * q2.z) - (q1.z * q2.y); | |
qr.y = (q1.w * q2.y) - (q1.x * q2.z) + (q1.y * q2.w) + (q1.z * q2.x); | |
qr.z = (q1.w * q2.z) + (q1.x * q2.y) - (q1.y * q2.x) + (q1.z * q2.w); | |
qr.w = (q1.w * q2.w) - (q1.x * q2.x) - (q1.y * q2.y) - (q1.z * q2.z); | |
return qr; | |
} | |
vec3 RotateVertex(vec3 position, vec3 axis, float angle) | |
{ | |
vec4 q = QuarternionFromAxisAngle(axis, angle); | |
vec3 v = position.xyz; | |
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); | |
} | |
void main() | |
{ | |
for (int k = 0; k < MAX_VERTICES; ++k) { | |
if (k < maxObjects) { | |
for(int i = 0; i < 3; ++i) { | |
vec3 trmVec = vec3(transformVector[7 * k + 0], transformVector[7 * k + 1] + 0.0, transformVector[7 * k + 2]); | |
vec3 rotVec = vec3(transformVector[7 * k + 3], transformVector[7 * k + 4], transformVector[7 * k + 5]); | |
float pitch = transformVector[7 * k + 3]; | |
float yaw = transformVector[7 * k + 4]; | |
float roll = transformVector[7 * k + 5]; | |
mat4 trm = translationMatrix(trmVec); | |
mat4 sm = scaleMatrix(vec3(1.05)); | |
#if 0 | |
mat4 rmz = rotationMatrix(vec3(0.0, 0.0, 1.0), roll); | |
mat4 rmy = rotationMatrix(vec3(0.0, 1.0, 0.0), yaw); | |
mat4 rmx = rotationMatrix(vec3(1.0, 0.0, 0.0), pitch); | |
mat4 rm = rmx * rmy * rmz; | |
//mat4 rm = rmz * rmx * rmy; | |
vec4 pos = trm * rm * sm * gl_in[i].gl_Position; | |
#else | |
vec3 P = (sm * gl_in[i].gl_Position).xyz; | |
//rotate | |
//P = RotateVertex(vec3(0.0), vec3(1.0, 0.0, 0.0), -rotVec[1]); | |
//P = RotateVertex(vec3(0.0), vec3(0.0, 1.0, 0.0), -rotVec[0]); | |
//P = RotateVertex(vec3(0.0), vec3(0.0, 0.0, 1.0), -rotVec[2]); | |
P = RotateVertex(P, vec3(0.0, 0.0, -1.0), roll); | |
P = RotateVertex(P, vec3(0.0, -1.0, 0.0), yaw); | |
P = RotateVertex(P, vec3(-1.0, 0.0, 0.0), pitch); | |
//transform | |
P += trmVec; | |
vec4 pos = vec4(P, 1.0); | |
#endif | |
float metal = transformVector[7 * k + 6]; | |
float x100 = 100.0 / (100.0 + metal); | |
float x1000 = 1000.0 / (1000.0 + metal); | |
float r = 1.0 - x1000; | |
float g = x1000 - x100; | |
float b = x100; | |
rgb = vec3(r, g, b); | |
gl_Position = projMat * viewMat * pos; | |
EmitVertex(); | |
} | |
EndPrimitive(); | |
} | |
} | |
} | |
]] | |
local vertexShaderCode = [[ | |
#version 150 compatibility | |
uniform mat4 projMat; | |
uniform mat4 viewMat; | |
void main(void) | |
{ | |
//gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; | |
//gl_Position = projMat * gl_ModelViewMatrix * gl_Vertex; | |
gl_Position = gl_Vertex; | |
} | |
]] | |
local fragShaderCode = [[ | |
#version 150 compatibility | |
flat in vec3 rgb; | |
uniform float alpha; | |
void main() | |
{ | |
gl_FragColor = vec4(rgb, alpha); | |
gl_FragColor = vec4(vec3(0.3), 1.0); | |
} | |
]] | |
local shaderObj | |
local transformVectorUniform | |
local maxObjectsUniform | |
local alphaUniform | |
local projMatUniform | |
local viewMatUniform | |
local modelMatUniform | |
local function DrawWorldFunc() | |
if (not hilite) and (spGetMapDrawMode() ~= 'metal') and (not WG.showeco) then | |
return | |
end | |
gl.DepthTest(true) | |
--gl.PolygonOffset(-2, -2) | |
gl.Blending(GL.SRC_ALPHA, GL.ONE) | |
local timer = widgetHandler:GetHourTimer() | |
local alpha = 0.25 + (0.75 * math.abs(1 - (timer * 2) % 2)) | |
local myAllyTeam = Spring.GetMyAllyTeamID() | |
local featureArray = {} | |
local features = Spring.GetAllFeatures() | |
--[[ | |
for _, fID in pairs(features) do | |
local metal = Spring.GetFeatureResources(fID) | |
if (metal and (metal > 1)) then | |
-- local aTeam = Spring.GetFeatureAllyTeam(fID) | |
-- if (aTeam ~= myAllyTeam) then | |
local x100 = 100 / (100 + metal) | |
local x1000 = 1000 / (1000 + metal) | |
local r = 1 - x1000 | |
local g = x1000 - x100 | |
local b = x100 | |
--gl.Color(r, g, b, alpha) | |
--gl.Feature(fID, true) | |
--gl.PushMatrix() | |
local x,y,z = Spring.GetFeaturePosition(fID) | |
--gl.Translate(x,y,z) | |
--gl.Color(r, g, b, alpha) | |
gl.UseShader(shaderObj) | |
gl.FeatureShape(Spring.GetFeatureDefID(fID), -1, true, true, true) | |
gl.UseShader(0) | |
--gl.PopMatrix() | |
-- end | |
end | |
end | |
]]-- | |
for _, fID in pairs(features) do | |
local fDefId = Spring.GetFeatureDefID(fID) | |
if not featureArray[fDefId] then | |
featureArray[fDefId] = {} | |
end | |
local x, y, z = Spring.GetFeaturePosition(fID) | |
local pi, ya, ro = Spring.GetFeatureRotation(fID) | |
local metal = Spring.GetFeatureResources(fID) | |
local arrLen = #featureArray[fDefId] | |
featureArray[fDefId][arrLen + 1] = x | |
featureArray[fDefId][arrLen + 2] = y | |
featureArray[fDefId][arrLen + 3] = z | |
featureArray[fDefId][arrLen + 4] = pi | |
featureArray[fDefId][arrLen + 5] = ya | |
featureArray[fDefId][arrLen + 6] = ro | |
featureArray[fDefId][arrLen + 7] = metal | |
end | |
for fDefId, array in pairs(featureArray) do | |
gl.UseShader(shaderObj) | |
gl.UniformInt(maxObjectsUniform, math.floor(#array / 7)) | |
gl.UniformArray(transformVectorUniform, 2, featureArray[fDefId]) | |
gl.Uniform(alphaUniform, alpha) | |
gl.UniformMatrix(projMatUniform, "projection") | |
gl.UniformMatrix(viewMatUniform, "view") | |
gl.FeatureShape(fDefId, -1, true, false, true) | |
gl.UseShader(0) | |
end | |
gl.Blending(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA) | |
--gl.PolygonOffset(false) | |
gl.DepthTest(false) | |
end | |
function widget:DrawWorld() | |
DrawWorldFunc() | |
end | |
function widget:DrawWorldRefraction() | |
DrawWorldFunc() | |
end | |
function widget:Initialize() | |
local GL_MAX_GEOMETRY_OUTPUT_VERTICES = 0x8DE0 | |
local GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = 0x8DE1 | |
local GL_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB | |
local GL_MAX_GEOMETRY_UNIFORM_COMPONENTS = 0x8DDF | |
local GL_MAX_TEXTURE_COORDS = 0x8871 | |
Spring.Echo("GL_MAX_GEOMETRY_OUTPUT_VERTICES", gl.GetNumber(GL_MAX_GEOMETRY_OUTPUT_VERTICES)) | |
Spring.Echo("GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS", gl.GetNumber(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS)) | |
Spring.Echo("GL_MAX_VERTEX_UNIFORM_VECTORS", gl.GetNumber(GL_MAX_VERTEX_UNIFORM_VECTORS)) | |
Spring.Echo("GL_MAX_GEOMETRY_UNIFORM_COMPONENTS", gl.GetNumber(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS)) | |
Spring.Echo("GL_MAX_TEXTURE_COORDS", gl.GetNumber(GL_MAX_TEXTURE_COORDS)) | |
--[[ | |
local maxVertices = math.min( | |
gl.GetNumber(GL_MAX_GEOMETRY_OUTPUT_VERTICES), | |
math.floor(gl.GetNumber(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS) / 12), --4 floats X 3 vertexes per triangle = 12 | |
math.floor(gl.GetNumber(GL_MAX_VERTEX_UNIFORM_VECTORS) * 4 / (3 + 4) ), --Number of 4 floats vectors in array. We will use 3 + 4 floats: 3 translation, 3 rotation, 1 metal value | |
math.floor(gl.GetNumber(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS) / (7 * 4) - ) -- 7 components ^^^^ each 4 bytes | |
) | |
]]-- | |
maxVertices = 32 | |
Spring.Echo("maxVertices", maxVertices) | |
geometryShaderCode = string.gsub(geometryShaderCode, "_MAX_VERT_", tostring(maxVertices)) | |
shaderObj = gl.CreateShader({ | |
vertex = vertexShaderCode, | |
geometry = geometryShaderCode, | |
fragment = fragShaderCode, | |
}) | |
Spring.Echo("GL_EXT_geometry_shader4", gl.HasExtension("GL_EXT_geometry_shader4")) | |
local shLog = gl.GetShaderLog() | |
if (shaderObj == nil or string.len(shLog or "") > 0) then | |
Spring.Echo("MetalFeatures->Shader: shader warnings & errors: "..shLog) | |
return false | |
end | |
transformVectorUniform = gl.GetUniformLocation(shaderObj, 'transformVector') | |
maxObjectsUniform = gl.GetUniformLocation(shaderObj, 'maxObjects') | |
alphaUniform = gl.GetUniformLocation(shaderObj, 'alpha') | |
projMatUniform = gl.GetUniformLocation(shaderObj, 'projMat') | |
viewMatUniform = gl.GetUniformLocation(shaderObj, 'viewMat') | |
end | |
function widget:Shutdown() | |
gl.DeleteShader(shaderObj) | |
end | |
local currCmd = spGetActiveCommand() --remember current command | |
function widget:Update() | |
if currCmd == spGetActiveCommand() then --if detect no change in command selection: --skip whole thing | |
return | |
end --else (command selection has change): perform check/automated-map-view-change | |
currCmd = spGetActiveCommand() --update active command | |
local activeCmd = spGetActiveCmdDesc(currCmd) | |
hilite = (activeCmd and (activeCmd.name == "Reclaim" or activeCmd.name == "Resurrect")) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment