diff --git a/planet/Graphics.ocg/AmbientShader.glsl b/planet/Graphics.ocg/AmbientShader.glsl deleted file mode 100644 index 3fe12fc1b..000000000 --- a/planet/Graphics.ocg/AmbientShader.glsl +++ /dev/null @@ -1,40 +0,0 @@ - -// Ambient light calculation - -#ifdef HAVE_LIGHT -uniform sampler2D ambientTex; - -uniform mat3x2 ambientTransform; -uniform float ambientBrightness; -#endif -//uniform float cullMode; // 0 if backface culling is enabled, 1 if it is disabled -// Already declared in LightShader.glsl - -slice(texture+6) -{ -#ifdef HAVE_LIGHT - // Ambient light - // Extra .xy since some old intel drivers return a vec3 - float ambient = texture2D(ambientTex, (ambientTransform * vec3(gl_FragCoord.xy, 1.0)).xy).r * ambientBrightness; -#else - // Lighting disabled: Ambient light everywhere - float ambient = 1.0; -#endif -} - -slice(light+1) -{ - // Add ambience to brightness -#ifdef LANDSCAPE - // For landscape, ambient brightness is coming from top - vec3 ambientDir = vec3(0.0, -1.0, 0.0); - light = mix(light, 1.0 + 1.0 * dot(normal, ambientDir), ambient); -#ifdef HAVE_2PX - light2 = mix(light2, 1.0 + 1.0 * dot(normal2, ambientDir), ambient); -#endif -#else - // For objects, ambient brightness is coming from the front - vec3 ambientDir = vec3(0.0, 0.0, 1.0); - light = mix(light, max(max(dot(normal, ambientDir), 0.0), cullMode * max(dot(-normal, ambientDir), 0.0)), ambient); -#endif -} diff --git a/planet/Graphics.ocg/CommonShader.glsl b/planet/Graphics.ocg/CommonShader.glsl new file mode 100644 index 000000000..bddaf91ea --- /dev/null +++ b/planet/Graphics.ocg/CommonShader.glsl @@ -0,0 +1,162 @@ + +// uncomment the following lines for debugging light directions: +// yellow: light up, blue: light down, turqoise: light right, pink: light left +// brightness: light strength +//#define LIGHT_DEBUG + +// uncomment the following lines for debugging light color: +// the light will always come from the front and have a uniform brightness. +//#define LIGHT_DEBUG_COLOR + +// uncomment the following lines to set the light color to pink for all lights for debugging: +//#define LIGHT_DEBUG_PINK + +// At what point of light intensity we set the "darkness" point. This +// is to compensate for the fact that the engine "smoothes" the light +// and therefore will often never arrive at 0 light intensity. +const float lightDarknessLevel = 8.0 / 256.0; + +#ifdef HAVE_LIGHT +uniform sampler2D ambientTex; + +uniform mat3x2 ambientTransform; +uniform float ambientBrightness; + +uniform sampler2D lightTex; +#endif + +// Gamma uniforms +uniform vec3 gamma; + +// 0 if backface culling is enabled, 1 if it is disabled +uniform float cullMode; + +// Light dot product, taking cull mode into account +float lightDot(vec3 normal, vec3 lightDir) { + return abs(max(-cullMode, dot(normalize(normal), lightDir))); +} + +vec3 extend_normal(vec2 v) +{ + // the higher the second value, the further away the light source from the landscape + return normalize(vec3(v, 0.45)); +} + +// Converts the pixel range 0.0..1.0 into the integer range 0..255 +int f2i(float x) { + return int(x * 255.9); +} + +slice(texture+5) +{ +#ifdef HAVE_LIGHT + + // Query light texture + vec2 lightDirCoord = lightCoord.st; + + vec4 lightPx = texture2D(lightTex, lightDirCoord); + float lightBright = 2.0*max(0.0, lightPx.a-lightDarknessLevel); + vec3 lightDir = extend_normal(vec2(1.0, 1.0) - lightPx.yz * 3.0); + + // Query light color texture (part of the light texture) + vec2 lightColorCoord = lightCoord.st - vec2(0.0, 0.5); // subtract offset for the color texture + + vec3 lightColor = texture2D(lightTex, lightColorCoord.st).rgb; + + // Normalise light colour + #ifdef LIGHT_DEBUG_COLOR + lightBright = 0.5; + lightColor = vec4(1.0, 0.0, 1.0, 1.0); + #endif +#else + // When lighting is disabled, put a light source coming from the camera. + // Note that in most cases this does not actually matter, since in the + // case with lighting disabled, ambient lighting takes fully over. + float lightBright = 0.5; + vec3 lightDir = vec3(0.0, 0.0, 1.0); + vec3 lightColor = vec3(1.0, 1.0, 1.0); +#endif + +#ifdef HAVE_LIGHT + // Ambient light + // Extra .xy since some old intel drivers return a vec3 + float ambient = texture2D(ambientTex, (ambientTransform * vec3(gl_FragCoord.xy, 1.0)).xy).r * ambientBrightness; +#else + // Lighting disabled: Ambient light everywhere + float ambient = 1.0; +#endif +} + +slice(light) +{ + + // Light dot product, taking backface culling into account + normal = normalize(normal); + float light = lightDot(normal, lightDir); + // Amount of reflection, depending on the angle where material reflects most + light = min(light / matAngle, 2.0 - light / matAngle); + +#ifdef LANDSCAPE + normal2 = normalize(normal2); + float light2 = lightDot(normal2, lightDir); + light2 = min(light2 / matAngle2, 2.0 - light2 / matAngle2); +#endif +} + +slice(light+1) +{ +#ifdef LANDSCAPE + // For landscape, ambient brightness is coming from top + vec3 ambientDir = normalize(vec3(0.0, -1.0, 1.0)); +#else + // For objects, ambient brightness is coming from the front + vec3 ambientDir = vec3(0.0, 0.0, 1.0); +#endif + // Add ambience to brightness + lightBright = mix(lightBright, 1.0, ambient); + light = mix(light, 0.5 * (ambient + lightDot(normal, ambientDir)), ambient); +#ifdef LANDSCAPE + light2 = mix(light2, 0.5 * (ambient + lightDot(normal2, ambientDir)), ambient); +#endif + lightColor = mix(lightColor, vec3(1.0,1.0,1.0), ambient); +} + +slice(color+5) +{ + // Normalize light colour + vec3 lightColorNorm = sqrt(3.0) * normalize(lightColor); + + // Add light. Depending on material properties, we make it more + // "spotty" and allow the material to self-illuminate. The light + // brightness overrules everything though (= FoW is last factor). + vec3 spotLight = pow(vec3(light,light,light), matSpot); + color.rgb = lightBright * color.rgb * (matEmit + lightColorNorm * spotLight); +#ifdef LANDSCAPE + vec3 spotLight2 = pow(vec3(light2,light2,light2), matSpot2); + color2.rgb = lightBright * color2.rgb * (matEmit2 + lightColorNorm * spotLight2); +#endif +} + +slice(finish+5) +{ + +#ifdef LIGHT_DEBUG +#ifdef HAVE_LIGHT + float lightYDir = lightPx.b - 1.0/3.0; + float lightXDir = lightPx.g - 1.0/3.0; + float lightStrength = lightPx.a; + color = + vec4(lightStrength * vec3(1.0-1.5*(max(0.0, lightYDir) + max(0.0,lightXDir)), + 1.0-1.5*(max(0.0, lightYDir) + max(0.0,-lightXDir)), + 1.0-1.5*max(0.0, -lightYDir)), + 1.0); +#else + color = vec4(0.0, 0.0, 0.0, 0.0); // invisible +#endif +#endif + +} + +slice(finish+10) { + color = vec4(pow(color.rgb, gamma), color.a); +} diff --git a/planet/Graphics.ocg/GammaShader.glsl b/planet/Graphics.ocg/GammaShader.glsl deleted file mode 100644 index af81d0d7a..000000000 --- a/planet/Graphics.ocg/GammaShader.glsl +++ /dev/null @@ -1,7 +0,0 @@ - -// Gamma uniforms -uniform vec3 gamma; - -slice(finish+10) { - color = vec4(pow(color.rgb, gamma), color.a); -} diff --git a/planet/Graphics.ocg/LandscapeShader.glsl b/planet/Graphics.ocg/LandscapeShader.glsl index ea370d74a..13a75cd5c 100644 --- a/planet/Graphics.ocg/LandscapeShader.glsl +++ b/planet/Graphics.ocg/LandscapeShader.glsl @@ -1,5 +1,4 @@ - // Input textures uniform sampler2D landscapeTex[2]; uniform sampler2D scalerTex; @@ -11,11 +10,7 @@ uniform vec2 resolution; // Center position uniform vec2 center; // Texture map -#ifndef NO_BROKEN_ARRAYS_WORKAROUND uniform sampler1D matMapTex; -#else -uniform float matMap[256]; -#endif uniform int materialDepth; uniform vec2 materialSize; @@ -25,20 +20,15 @@ const vec2 scalerStepY = vec2(0.0, 1.0 / 32.0); const vec2 scalerOffset = scalerStepX / 3.0 + scalerStepY / 3.0; const vec2 scalerPixel = vec2(scalerStepX.x, scalerStepY.y) / 3.0; -// Parameters +// How much % the normals from the normal map are added up to the +// landscape normal. The higher the strength, the more structure +// within the material is visible but also the less the borders +// between the different materials stand out. +const float normalMapStrength = 0.20; -// how much % the normals from the normal map are added up to the landscape normal. The higher the strength, the more -// structure within the material is visible but also the less the borders between the different materials stand out. -const float normalMapStrength = 0.75; - -float queryMatMap(int pix) +vec4 queryMatMap(int pix) { -#ifndef NO_BROKEN_ARRAYS_WORKAROUND - int idx = f2i(texture1D(matMapTex, float(pix) / 256.0 + 0.5 / 256.0).r); - return float(idx) / 256.0 + 0.5 / float(materialDepth); -#else - return matMap[pix]; -#endif + return texture1D(matMapTex, float(pix) / 2.0 / 256.0 + 0.5 / 2.0 / 256.0); } slice(coordinate) @@ -63,44 +53,74 @@ slice(texture) // our pixel color (without/with interpolation) vec4 landscapePx = texture2D(landscapeTex[0], centerCoo); vec4 realLandscapePx = texture2D(landscapeTex[0], texCoo); + + // find scaler coordinate + vec2 scalerCoo = scalerOffset + mod(pixelCoo, vec2(1.0, 1.0)) * scalerPixel; + int iScaler = f2i(landscapePx.a), iRow = iScaler / 8; + scalerCoo.x += float(iScaler - iRow * 8) / 8.0; + scalerCoo.y += float(iScaler / 8) / 32.0; + + // query scaler texture + vec4 scalerPx = texture2D(scalerTex, scalerCoo); + + // Get "second" landscape pixel + vec2 centerCoo2 = centerCoo + fullStep * floor(vec2(-0.5, -0.5) + + scalerPx.gb * 255.0 / 64.0); + vec4 landscapePx2 = texture2D(landscapeTex[0], centerCoo2); + } slice(material) { - // Get material pixels - float materialIx = queryMatMap(f2i(landscapePx.r)); + // Get material properties from material map + int matMapIx = f2i(landscapePx.r); + vec4 matMap = queryMatMap(2*matMapIx); + vec4 matMapX = queryMatMap(2*matMapIx+1); + float materialIx = float(f2i(matMap.a)) / 256.0 + 0.5 / float(materialDepth); + vec3 matEmit = matMap.rgb; + vec3 matSpot = matMapX.rgb * 255.9f / 16.0f; + float matAngle = matMapX.a; + + // Query material texture pixels vec4 materialPx = texture3D(materialTex, vec3(materialCoo, materialIx)); vec4 normalPx = texture3D(materialTex, vec3(materialCoo, materialIx+0.5)); - // Same for second pixel, but we'll simply use the first normal -#ifdef HAVE_2PX - float materialIx2 = queryMatMap(f2i(landscapePx2.r)); + // Same for second pixel + int matMapIx2 = f2i(landscapePx2.r); + vec4 matMap2 = queryMatMap(2*matMapIx2); + vec4 matMapX2 = queryMatMap(2*matMapIx2+1); + float materialIx2 = float(f2i(matMap2.a)) / 256.0 + 0.5 / float(materialDepth); + vec3 matEmit2 = matMap2.rgb; + vec3 matSpot2 = matMapX2.rgb * 255.9f / 16.0f; + float matAngle2 = matMapX2.a; + + // Query material texture pixels vec4 materialPx2 = texture3D(materialTex, vec3(materialCoo, materialIx2)); vec4 normalPx2 = texture3D(materialTex, vec3(materialCoo, materialIx2+0.5)); -#endif } slice(normal) { // Normal calculation - vec3 normal = extend_normal(mix(realLandscapePx.yz, landscapePx.yz, scalerPx.a) - - vec2(0.5, 0.5)); + vec3 normal = extend_normal(1.5 * (mix(realLandscapePx.yz, landscapePx.yz, scalerPx.a) + - vec2(0.5, 0.5))); vec3 textureNormal = normalPx.xyz - vec3(0.5,0.5,0.5); - normal = normal + textureNormal * normalMapStrength; + normal = mix(textureNormal, normal, normalMapStrength); -#ifdef HAVE_2PX vec3 normal2 = extend_normal(landscapePx2.yz - vec2(0.5, 0.5)); vec3 textureNormal2 = normalPx2.xyz - vec3(0.5,0.5,0.5); - normal2 = normal2 + textureNormal2 * normalMapStrength; -#endif + normal2 = mix(textureNormal2, normal2, normalMapStrength); } slice(color) { #define color gl_FragColor color = materialPx; -#ifdef HAVE_2PX vec4 color2 = materialPx2; -#endif +} + +slice(color+10) { + // Mix second color into main color according to scaler + color = mix(color2, color, scalerPx.r); } diff --git a/planet/Graphics.ocg/LightShader.glsl b/planet/Graphics.ocg/LightShader.glsl deleted file mode 100644 index 985e8a527..000000000 --- a/planet/Graphics.ocg/LightShader.glsl +++ /dev/null @@ -1,99 +0,0 @@ - -// Base light calculations - -#ifdef HAVE_LIGHT -uniform sampler2D lightTex; -#endif -uniform float cullMode; // 0 if backface culling is enabled, 1 if it is disabled - -// uncomment the following lines for debugging light directions: -// yellow: light up, blue: light down, turqoise: light right, pink: light left -// brightness: light strength -//#define LIGHT_DEBUG - -// uncomment the following lines for debugging light color: -// the light will always come from the front and have a uniform brightness. -//#define LIGHT_DEBUG_COLOR - -// uncomment the following lines to set the light color to pink for all lights for debugging: -//#define LIGHT_DEBUG_PINK - -// At what point of light intensity we set the "darkness" point. This -// is to compensate for the fact that the engine "smoothes" the light -// and therefore will often never arrive at 0 light intensity. -const float lightDarknessLevel = 8.0 / 256.0; - -slice(texture+5) -{ -#ifdef HAVE_LIGHT - - // Query light texture - vec2 lightDirCoord = lightCoord.st; - - vec4 lightPx = texture2D(lightTex, lightDirCoord); - float lightBright = max(0.0, lightPx.a-lightDarknessLevel); - vec3 lightDir = extend_normal(vec2(1.0, 1.0) - lightPx.yz * 3.0); - - // Query light color texture (part of the light texture) - vec2 lightColorCoord = lightCoord.st - vec2(0.0, 0.5); // subtract offset for the color texture - - vec4 lightColor = texture2D(lightTex, lightColorCoord.st); - - #ifdef LIGHT_DEBUG_COLOR - lightBright = 0.5; - lightDir = vec3(0.0, 0.0, 1.0); - #endif -#else - // When lighting is disabled, put a light source coming from the camera. - // Note that in most cases this does not actually matter, since in the - // case with lighting disabled, ambient lighting takes fully over. - float lightBright = 0.5; - vec3 lightDir = vec3(0.0, 0.0, 1.0); - - vec4 lightColor = vec4(1.0, 1.0, 1.0, 1.0); -#endif -} - -slice(light) -{ - float light = 2.0 * lightBright * max(max(dot(normal, lightDir), 0.0), cullMode * max(dot(-normal, lightDir), 0.0)); -#ifdef HAVE_2PX - float light2 = 2.0 * lightBright * max(max(dot(normal2, lightDir), 0.0), cullMode * max(dot(-normal2, lightDir), 0.0)); -#endif -} - -slice(color+5) -{ - // pink shade for debugging! - #ifdef LIGHT_DEBUG_PINK - lightColor = vec4(1.0, 0.0, 1.0, 1.0); - #endif - - lightColor.rgb = sqrt(3.0) * normalize(lightColor.rgb); - - // Add light - color.rgb = light * color.rgb * lightColor.rgb; -#ifdef HAVE_2PX - color2.rgb = light2 * color2.rgb * lightColor.rgb; -#endif -} - -slice(finish+5) -{ - -#ifdef LIGHT_DEBUG -#ifdef HAVE_LIGHT - float lightYDir = lightPx.b - 1.0/3.0; - float lightXDir = lightPx.g - 1.0/3.0; - float lightStrength = lightPx.a; - color = - vec4(lightStrength * vec3(1.0-1.5*(max(0.0, lightYDir) + max(0.0,lightXDir)), - 1.0-1.5*(max(0.0, lightYDir) + max(0.0,-lightXDir)), - 1.0-1.5*max(0.0, -lightYDir)), - 1.0); -#else - color = vec4(0.0, 0.0, 0.0, 0.0); // invisible -#endif -#endif - -} diff --git a/planet/Graphics.ocg/ObjectBaseShader.glsl b/planet/Graphics.ocg/ObjectBaseShader.glsl deleted file mode 100644 index cf9b7b376..000000000 --- a/planet/Graphics.ocg/ObjectBaseShader.glsl +++ /dev/null @@ -1,35 +0,0 @@ -uniform vec4 clrMod; - -slice(init) -{ -#define color gl_FragColor - -#ifdef MESH - // TODO: Add emission part of the material. Note we cannot just - // add this to the color, but it would need to be handled separately, - // such that it is independent from the incident light direction. - color = gl_FrontMaterial.diffuse; -#else - vec4 baseColor = gl_Color; - color = baseColor; -#endif - -} - -slice(color) -{ - // TODO: Instead of a conditional, we could compute the color as - // color = A + B*color + C*clrMod + D*color*clrMod; - // Then, mod2 would be A=-0.5, B=1, C=1, D=0 - // and default would be A=0,B=0,C=0,D=1 - // Would allow to avoid conditionsals and #ifdefs, but need 4 uniforms... - - // Could also try some sort of 3x3 matrix: - // out = (color, clrmod, 1) * (A,B,C,D,E,F,0,0,G) * (color, clrmod, 1) - -#ifdef CLRMOD_MOD2 - color = clamp(color + clrMod - 0.5, 0.0, 1.0); -#else - color = color * clrMod; -#endif -} diff --git a/planet/Graphics.ocg/ObjectLightShader.glsl b/planet/Graphics.ocg/ObjectLightShader.glsl deleted file mode 100644 index 5487a0668..000000000 --- a/planet/Graphics.ocg/ObjectLightShader.glsl +++ /dev/null @@ -1,43 +0,0 @@ -uniform mat3x2 lightTransform; -#ifdef HAVE_NORMALMAP -uniform sampler2D normalTex; -#endif - -#ifdef MESH -varying vec3 normalDir; -#endif - -slice(texture+4) -{ -#ifdef HAVE_LIGHT - // prepare texture coordinate for light lookup in LightShader.c - // Extra .xy since some old intel drivers return a vec3 - vec2 lightCoord = (lightTransform * vec3(gl_FragCoord.xy, 1.0)).xy; -#endif -} - -slice(normal) -{ -#ifdef HAVE_NORMALMAP - vec4 normalPx = texture2D(normalTex, texcoord.xy); - vec3 normalPxDir = 2.0 * (normalPx.xyz - vec3(0.5, 0.5, 0.5)); -#ifdef MESH - // For meshes, the normal matrix is typically provided in Clonk - // coordinates, but the normal matrix incorporates a component that - // transforms from Ogre to Clonk coordinates. Therefore, we need to - // reverse that transformation for meshes. - // TODO: This could be optimized since the matrix is so simple that - // we don't need to do a full matrix multiplication. - mat3 c2o = mat3(0.0, 1.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0); - vec3 normal = normalize(c2o * gl_NormalMatrix * normalPxDir); -#else - vec3 normal = normalize(gl_NormalMatrix * normalPxDir); -#endif -#else -#ifdef MESH - vec3 normal = normalDir; // Normal matrix is already applied in vertex shader -#else - vec3 normal = vec3(0.0, 0.0, 1.0); -#endif -#endif -} diff --git a/planet/Graphics.ocg/ObjectShader.glsl b/planet/Graphics.ocg/ObjectShader.glsl new file mode 100644 index 000000000..506fe2c1f --- /dev/null +++ b/planet/Graphics.ocg/ObjectShader.glsl @@ -0,0 +1,109 @@ + +uniform mat3x2 lightTransform; + +#ifdef HAVE_NORMALMAP +uniform sampler2D normalTex; +#endif + +#ifdef MESH +varying vec3 normalDir; +#endif + +uniform vec4 clrMod; + +#ifdef HAVE_BASE +uniform sampler2D baseTex; +#endif + +#ifdef HAVE_OVERLAY +uniform vec4 overlayClr; +uniform sampler2D overlayTex; +#endif + +slice(material) +{ + // Default material properties. TODO: Populate them? + vec3 matEmit = vec3(0.0,0.0,0.0); + vec3 matSpot = vec3(1.0,1.0,1.0); + float matAngle = 1.0; +} + +slice(texture) +{ +#define color gl_FragColor + +#ifdef MESH + // TODO: Add emission part of the material. Note we cannot just + // add this to the color, but it would need to be handled separately, + // such that it is independent from the incident light direction. + color = gl_FrontMaterial.diffuse; +#else + vec4 baseColor = gl_Color; + color = baseColor; +#endif + +#ifdef HAVE_BASE + color = baseColor * texture2D(baseTex, texcoord.xy); +#endif + +#ifdef HAVE_OVERLAY + // Get overlay color from overlay texture + vec4 overlay = baseColor * overlayClr * texture2D(overlayTex, texcoord.xy); + // Mix overlay with texture + float alpha0 = 1.0 - (1.0 - color.a) * (1.0 - overlay.a); + color = vec4(mix(color.rgb, overlay.rgb, overlay.a / alpha0), alpha0); +#endif +} + +slice(texture+4) +{ +#ifdef HAVE_LIGHT + // prepare texture coordinate for light lookup in LightShader.c + // Extra .xy since some old intel drivers return a vec3 + vec2 lightCoord = (lightTransform * vec3(gl_FragCoord.xy, 1.0)).xy; +#endif +} + +slice(normal) +{ +#ifdef HAVE_NORMALMAP + vec4 normalPx = texture2D(normalTex, texcoord.xy); + vec3 normalPxDir = 2.0 * (normalPx.xyz - vec3(0.5, 0.5, 0.5)); +#ifdef MESH + // For meshes, the normal matrix is typically provided in Clonk + // coordinates, but the normal matrix incorporates a component that + // transforms from Ogre to Clonk coordinates. Therefore, we need to + // reverse that transformation for meshes. + // TODO: This could be optimized since the matrix is so simple that + // we don't need to do a full matrix multiplication. + mat3 c2o = mat3(0.0, 1.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0); + vec3 normal = normalize(c2o * gl_NormalMatrix * normalPxDir); +#else + vec3 normal = normalize(gl_NormalMatrix * normalPxDir); +#endif +#else +#ifdef MESH + vec3 normal = normalDir; // Normal matrix is already applied in vertex shader +#else + vec3 normal = vec3(0.0, 0.0, 1.0); +#endif +#endif +} + +slice(color) +{ + // TODO: Instead of a conditional, we could compute the color as + // color = A + B*color + C*clrMod + D*color*clrMod; + // Then, mod2 would be A=-0.5, B=1, C=1, D=0 + // and default would be A=0,B=0,C=0,D=1 + // Would allow to avoid conditionsals and #ifdefs, but need 4 uniforms... + + // Could also try some sort of 3x3 matrix: + // out = (color, clrmod, 1) * (A,B,C,D,E,F,0,0,G) * (color, clrmod, 1) + +#ifdef HAVE_MOD2 + color = clamp(color + clrMod - 0.5, 0.0, 1.0); +#else + color = color * clrMod; +#endif +} diff --git a/planet/Graphics.ocg/ScalerShader.glsl b/planet/Graphics.ocg/ScalerShader.glsl deleted file mode 100644 index a338e3886..000000000 --- a/planet/Graphics.ocg/ScalerShader.glsl +++ /dev/null @@ -1,49 +0,0 @@ - -#define HAVE_2PX - -slice(texture+5) -{ - // find scaler coordinate - vec2 scalerCoo = scalerOffset + mod(pixelCoo, vec2(1.0, 1.0)) * scalerPixel; - -#ifdef SCALER_IN_GPU - if(texture2D(landscapeTex[0], centerCoo - fullStepX - fullStepY).r == landscapePx.r) - scalerCoo += scalerStepX; - if(texture2D(landscapeTex[0], centerCoo - fullStepY).r == landscapePx.r) - scalerCoo += 2.0 * scalerStepX; - if(texture2D(landscapeTex[0], centerCoo + fullStepX - fullStepY).r == landscapePx.r) - scalerCoo += 4.0 * scalerStepX; - - if(texture2D(landscapeTex[0], centerCoo - fullStepX ).r == landscapePx.r) - scalerCoo += scalerStepY; - if(texture2D(landscapeTex[0], centerCoo + fullStepX ).r == landscapePx.r) - scalerCoo += 2.0 * scalerStepY; - - if(texture2D(landscapeTex[0], centerCoo - fullStepX + fullStepY).r == landscapePx.r) - scalerCoo += 4.0 * scalerStepY; - if(texture2D(landscapeTex[0], centerCoo + fullStepY).r == landscapePx.r) - scalerCoo += 8.0 * scalerStepY; - if(texture2D(landscapeTex[0], centerCoo + fullStepX + fullStepY).r == landscapePx.r) - scalerCoo += 16.0 * scalerStepY; -#else - int iScaler = f2i(landscapePx.a), iRow = iScaler / 8; - scalerCoo.x += float(iScaler - iRow * 8) / 8.0; - scalerCoo.y += float(iScaler / 8) / 32.0; -#endif - - // Note: scalerCoo will jump around a lot, causing some GPUs to - // apparantly get confused with the level-of-detail - // calculation. We therefore try to disable LOD. - vec4 scalerPx = texture2DLod(scalerTex, scalerCoo, 0.0); - - // gen3 other coordinate calculation. Still struggles a bit with 3-ways - vec2 centerCoo2 = centerCoo + fullStep * floor(vec2(-0.5, -0.5) + - scalerPx.gb * 255.0 / 64.0); - vec4 landscapePx2 = texture2D(landscapeTex[0], centerCoo2); - -} - -slice(color+10) { - // Mix second color into main color according to scaler - color = mix(color2, color, scalerPx.r); -} diff --git a/planet/Graphics.ocg/SpriteOverlayShader.glsl b/planet/Graphics.ocg/SpriteOverlayShader.glsl deleted file mode 100644 index 4d10f1cec..000000000 --- a/planet/Graphics.ocg/SpriteOverlayShader.glsl +++ /dev/null @@ -1,11 +0,0 @@ -uniform vec4 overlayClr; -uniform sampler2D overlayTex; - -slice(texture+1) -{ - // Get overlay color from overlay texture - vec4 overlay = baseColor * overlayClr * texture2D(overlayTex, texcoord.xy); - // Mix overlay with texture - float alpha0 = 1.0 - (1.0 - color.a) * (1.0 - overlay.a); - color = vec4(mix(color.rgb, overlay.rgb, overlay.a / alpha0), alpha0); -} diff --git a/planet/Graphics.ocg/SpriteTextureShader.glsl b/planet/Graphics.ocg/SpriteTextureShader.glsl deleted file mode 100644 index 13b916c2b..000000000 --- a/planet/Graphics.ocg/SpriteTextureShader.glsl +++ /dev/null @@ -1,6 +0,0 @@ -uniform sampler2D baseTex; - -slice(texture) -{ - color = baseColor * texture2D(baseTex, texcoord.xy); -} diff --git a/planet/Graphics.ocg/UtilShader.glsl b/planet/Graphics.ocg/UtilShader.glsl deleted file mode 100644 index 307ed54a1..000000000 --- a/planet/Graphics.ocg/UtilShader.glsl +++ /dev/null @@ -1,17 +0,0 @@ - -// #ifdef NO_TEXTURE_LOD_IN_FRAGMENT -#define texture1DLod(t,c,l) texture1D(t,c) -#define texture2DLod(t,c,l) texture2D(t,c) -// #endif - -vec3 extend_normal(vec2 v) -{ - // the higher the second value, the further away the light source from the landscape - return normalize(vec3(v, 0.45)); -} - -// Converts the pixel range 0.0..1.0 into the integer range 0..255 -int f2i(float x) { - return int(x * 255.9); -} - diff --git a/planet/Material.ocg/Gold.ocm b/planet/Material.ocg/Gold.ocm index 42d68a316..8bf108140 100644 --- a/planet/Material.ocg/Gold.ocm +++ b/planet/Material.ocg/Gold.ocm @@ -9,4 +9,7 @@ Blast2ObjectRatio=100 MaxAirSpeed=100 MaxSlide=1 Placement=50 -TextureOverlay=gold \ No newline at end of file +TextureOverlay=gold +LightEmit=0,215,255 +LightSpot=64,64,64 +LightAngle=220 diff --git a/src/graphics/C4DrawGL.cpp b/src/graphics/C4DrawGL.cpp index d3beca553..38ac28d57 100644 --- a/src/graphics/C4DrawGL.cpp +++ b/src/graphics/C4DrawGL.cpp @@ -598,22 +598,15 @@ bool CStdGL::CreateSpriteShader(C4Shader& shader, const char* name, int ssc, C4G shader.AddTexCoord("texcoord"); // Then load slices for fragment shader - shader.AddFragmentSlice(-1, "#define OPENCLONK"); - if (ssc & C4SSC_MOD2) shader.AddFragmentSlice(-1, "#define CLRMOD_MOD2"); + shader.AddFragmentSlice(-1, "#define OPENCLONK\n#define SPRITE"); + if (ssc & C4SSC_MOD2) shader.AddFragmentSlice(-1, "#define HAVE_MOD2"); if (ssc & C4SSC_NORMAL) shader.AddFragmentSlice(-1, "#define HAVE_NORMALMAP"); if (ssc & C4SSC_LIGHT) shader.AddFragmentSlice(-1, "#define HAVE_LIGHT"); - shader.LoadSlices(pGroups, "UtilShader.glsl"); - shader.LoadSlices(pGroups, "ObjectBaseShader.glsl"); + if (ssc & C4SSC_BASE) shader.AddFragmentSlice(-1, "#define HAVE_BASE"); + if (ssc & C4SSC_OVERLAY) shader.AddFragmentSlice(-1, "#define HAVE_OVERLAY"); - if (ssc & C4SSC_BASE) shader.LoadSlices(pGroups, "SpriteTextureShader.glsl"); - if (ssc & C4SSC_OVERLAY) shader.LoadSlices(pGroups, "SpriteOverlayShader.glsl"); - - // In case light is disabled, these shaders use a default light source - // (typically ambient light everywhere). - shader.LoadSlices(pGroups, "ObjectLightShader.glsl"); - shader.LoadSlices(pGroups, "LightShader.glsl"); - shader.LoadSlices(pGroups, "AmbientShader.glsl"); - shader.LoadSlices(pGroups, "GammaShader.glsl"); + shader.LoadSlices(pGroups, "CommonShader.glsl"); + shader.LoadSlices(pGroups, "ObjectShader.glsl"); if (!shader.Init(name, uniformNames)) { diff --git a/src/landscape/C4LandscapeRender.cpp b/src/landscape/C4LandscapeRender.cpp index 2dccdc311..d7a4618b9 100644 --- a/src/landscape/C4LandscapeRender.cpp +++ b/src/landscape/C4LandscapeRender.cpp @@ -537,15 +537,11 @@ bool C4LandscapeRenderGL::LoadShader(C4GroupSet *pGroups, C4Shader& shader, cons if(ssc & C4SSC_LIGHT) hLightTexCoord = shader.AddTexCoord("lightCoord"); // Then load slices for fragment shader - shader.AddFragmentSlice(-1, "#define LANDSCAPE"); + shader.AddFragmentSlice(-1, "#define OPENCLONK\n#define LANDSCAPE"); if(ssc & C4SSC_LIGHT) shader.AddFragmentSlice(-1, "#define HAVE_LIGHT"); // sample light from light texture - shader.LoadSlices(pGroups, "UtilShader.glsl"); + shader.LoadSlices(pGroups, "CommonShader.glsl"); shader.LoadSlices(pGroups, "LandscapeShader.glsl"); - shader.LoadSlices(pGroups, "LightShader.glsl"); - shader.LoadSlices(pGroups, "AmbientShader.glsl"); - shader.LoadSlices(pGroups, "ScalerShader.glsl"); - shader.LoadSlices(pGroups, "GammaShader.glsl"); // Initialise! if (!shader.Init(name, UniformNames)) { @@ -578,7 +574,6 @@ bool C4LandscapeRenderGL::LoadShaders(C4GroupSet *pGroups) UniformNames[C4LRU_Gamma] = "gamma"; UniformNames[C4LRU_Resolution] = "resolution"; UniformNames[C4LRU_Center] = "center"; - UniformNames[C4LRU_MatMap] = "matMap"; UniformNames[C4LRU_MatMapTex] = "matMapTex"; UniformNames[C4LRU_MaterialDepth] = "materialDepth"; UniformNames[C4LRU_MaterialSize] = "materialSize"; @@ -800,7 +795,7 @@ void C4LandscapeRenderGL::AddTexturesFromMap(C4TextureMap *pMap) } -void C4LandscapeRenderGL::BuildMatMap(GLfloat *pFMap, GLubyte *pIMap) +void C4LandscapeRenderGL::BuildMatMap(uint32_t *pTex) { // TODO: Still merely an inefficient placeholder for things to come... @@ -812,8 +807,8 @@ void C4LandscapeRenderGL::BuildMatMap(GLfloat *pFMap, GLubyte *pIMap) if(!pEntry->GetTextureName()) { // Undefined textures transparent - if(pFMap) pFMap[pix] = 0.5 / iMaterialTextureDepth; - if(pIMap) pIMap[pix] = 0; + pTex[2*pix] = 0; + pTex[2*pix+1] = RGBA(0,0,0,255); continue; } @@ -821,8 +816,13 @@ void C4LandscapeRenderGL::BuildMatMap(GLfloat *pFMap, GLubyte *pIMap) int iPhases = 1; const char *p = pEntry->GetTextureName(); while((p = strchr(p, '-'))) { p++; iPhases++; } // Hard-coded hack. Fix me! - const int iPhaseLength = 300; - float phase = (iPhases == 1 ? 0 : float(C4TimeMilliseconds::Now().AsInt() % (iPhases * iPhaseLength)) / iPhaseLength); + C4Material *pMaterial = pEntry->GetMaterial(); + const int iPhaseLength = pMaterial->AnimationSpeed; + float phase = 0; + if (iPhases > 1) { + phase = C4TimeMilliseconds::Now().AsInt() % (iPhases * iPhaseLength); + phase /= iPhaseLength; + } // Find our transition const char *pFrom = pEntry->GetTextureName(); @@ -851,8 +851,17 @@ void C4LandscapeRenderGL::BuildMatMap(GLfloat *pFMap, GLubyte *pIMap) } // Assign texture - if(pFMap) pFMap[pix] = (gTexCoo + 0.5) / iMaterialTextureDepth; - if(pIMap) pIMap[pix] = int((gTexCoo * 256.0 / iMaterialTextureDepth) + 0.5); + int iTexCoo = int((gTexCoo * 256.0 / iMaterialTextureDepth) + 0.5); + pTex[2*pix] = RGBA( + Clamp(pMaterial->LightEmit[0], 0, 255), + Clamp(pMaterial->LightEmit[1], 0, 255), + Clamp(pMaterial->LightEmit[2], 0, 255), + iTexCoo); + pTex[2*pix+1] = RGBA( + Clamp(pMaterial->LightSpot[0], 0, 255), + Clamp(pMaterial->LightSpot[1], 0, 255), + Clamp(pMaterial->LightSpot[2], 0, 255), + Clamp(pMaterial->LightAngle, 0, 255)); } } @@ -889,12 +898,6 @@ void C4LandscapeRenderGL::Draw(const C4TargetFacet &cgo, const C4FoWRegion *Ligh ShaderCall.SetUniform2f(C4LRU_Center, centerX / float(Surfaces[0]->Wdt), centerY / float(Surfaces[0]->Hgt)); - if (shader->HaveUniform(C4LRU_MatMap)) - { - GLfloat MatMap[256]; - BuildMatMap(MatMap, NULL); - ShaderCall.SetUniform1fv(C4LRU_MatMap, 256, MatMap); - } ShaderCall.SetUniform1i(C4LRU_MaterialDepth, iMaterialTextureDepth); ShaderCall.SetUniform2f(C4LRU_MaterialSize, float(iMaterialWidth) / ::Game.C4S.Landscape.MaterialZoom, @@ -960,9 +963,9 @@ void C4LandscapeRenderGL::Draw(const C4TargetFacet &cgo, const C4FoWRegion *Ligh } if(ShaderCall.AllocTexUnit(C4LRU_MatMapTex, GL_TEXTURE_1D)) { - GLubyte MatMap[256]; - BuildMatMap(NULL, MatMap); - glTexImage1D(GL_TEXTURE_1D, 0, 1, 256, 0, GL_RED, GL_UNSIGNED_BYTE, MatMap); + uint32_t MatMap[2*256]; + BuildMatMap(MatMap); + glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, 2*256, 0, GL_RGBA, GL_UNSIGNED_BYTE, MatMap); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } diff --git a/src/landscape/C4LandscapeRender.h b/src/landscape/C4LandscapeRender.h index 032858f18..819353519 100644 --- a/src/landscape/C4LandscapeRender.h +++ b/src/landscape/C4LandscapeRender.h @@ -45,7 +45,6 @@ enum C4LR_Uniforms C4LRU_Gamma, C4LRU_Resolution, C4LRU_Center, - C4LRU_MatMap, C4LRU_MatMapTex, C4LRU_MaterialDepth, C4LRU_MaterialSize, @@ -150,7 +149,7 @@ private: void AddTextureTransition(const char *szFrom, const char *szTo); void AddTextureAnim(const char *szTextureAnim); void AddTexturesFromMap(C4TextureMap *pMap); - void BuildMatMap(GLfloat *pFMap, GLubyte *pIMap); + void BuildMatMap(uint32_t *pTex); }; #endif diff --git a/src/landscape/C4Material.cpp b/src/landscape/C4Material.cpp index 4d3198885..cc562f7da 100644 --- a/src/landscape/C4Material.cpp +++ b/src/landscape/C4Material.cpp @@ -267,6 +267,12 @@ void C4MaterialCore::Clear() MinHeightCount = 0; SplashRate=10; KeepSinglePixels=false; + AnimationSpeed = 20; + LightAngle = 255; + for (int i = 0; i < 3; i++) { + LightEmit[i] = 0; + LightSpot[i] = 16; + } } void C4MaterialCore::Default() @@ -304,7 +310,6 @@ void C4MaterialCore::CompileFunc(StdCompiler *pComp) if (pComp->isCompiler()) Clear(); pComp->Name("Material"); pComp->Value(mkNamingAdapt(toC4CStr(Name), "Name", "")); - pComp->Value(mkNamingAdapt(ColorAnimation, "ColorAnimation", 0)); const StdEnumEntry Shapes[] = { @@ -368,6 +373,10 @@ void C4MaterialCore::CompileFunc(StdCompiler *pComp) pComp->Value(mkNamingAdapt(MinHeightCount, "MinHeightCount", 0)); pComp->Value(mkNamingAdapt(SplashRate, "SplashRate", 10)); pComp->Value(mkNamingAdapt(KeepSinglePixels, "KeepSinglePixels", false)); + pComp->Value(mkNamingAdapt(AnimationSpeed, "AnimationSpeed", 100)); + pComp->Value(mkNamingAdapt(LightAngle, "LightAngle", 255)); + pComp->Value(mkNamingAdapt(mkArrayAdaptDM(LightEmit, 0), "LightEmit")); + pComp->Value(mkNamingAdapt(mkArrayAdaptDM(LightSpot, 16),"LightSpot")); pComp->NameEnd(); // material reactions pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(CustomReactionList), diff --git a/src/landscape/C4Material.h b/src/landscape/C4Material.h index 70b674bb0..57d34a5a0 100644 --- a/src/landscape/C4Material.h +++ b/src/landscape/C4Material.h @@ -180,6 +180,10 @@ public: int32_t MinHeightCount; // minimum material thickness in order for it to be counted int32_t SplashRate; bool KeepSinglePixels; // if true, single pixels are not destroyed (for vehicle) + int32_t AnimationSpeed; // frames per animation phase + int32_t LightAngle; // light angle at which we have maximum reflection + int32_t LightEmit[3]; // amount the material lights up itself + int32_t LightSpot[3]; // spot strength void Clear(); void Default(); diff --git a/src/lib/StdMeshMaterial.cpp b/src/lib/StdMeshMaterial.cpp index b6ddbfd79..eb0f8a579 100644 --- a/src/lib/StdMeshMaterial.cpp +++ b/src/lib/StdMeshMaterial.cpp @@ -854,7 +854,6 @@ bool StdMeshMaterialProgram::AddParameterNames(const StdMeshMaterialShaderParame bool StdMeshMaterialProgram::CompileShader(StdMeshMaterialLoader& loader, C4Shader& shader, int ssc) { // Add standard slices - shader.AddFragmentSlice(-1, "#define MESH"); loader.AddShaderSlices(shader, ssc); // Add our slices shader.AddVertexSlice(-1, "varying vec2 texcoord;"); diff --git a/src/object/C4Def.cpp b/src/object/C4Def.cpp index a2ca88720..be9b80e57 100644 --- a/src/object/C4Def.cpp +++ b/src/object/C4Def.cpp @@ -61,27 +61,15 @@ public: { #ifndef USE_CONSOLE // Add mesh-independent slices - shader.AddFragmentSlice(-1, "#define OPENCLONK"); - shader.AddVertexSlice(-1, "#define OPENCLONK"); - - if (ssc & C4SSC_MOD2) shader.AddFragmentSlice(-1, "#define CLRMOD_MOD2"); + shader.AddFragmentSlice(-1, "#define OPENCLONK\n#define MESH"); + shader.AddVertexSlice(-1, "#define OPENCLONK\n#define MESH"); + if (ssc & C4SSC_MOD2) shader.AddFragmentSlice(-1, "#define HAVE_MOD2"); if (ssc & C4SSC_LIGHT) shader.AddFragmentSlice(-1, "#define HAVE_LIGHT"); + if (ssc & C4SSC_BASE) shader.AddFragmentSlice(-1, "#define HAVE_LIGHT"); + if (ssc & C4SSC_OVERLAY) shader.AddFragmentSlice(-1, "#define HAVE_LIGHT"); - shader.LoadSlices(&::GraphicsResource.Files, "UtilShader.glsl"); - shader.LoadSlices(&::GraphicsResource.Files, "ObjectBaseShader.glsl"); - shader.LoadSlices(&::GraphicsResource.Files, "MeshShader.glsl"); - shader.LoadSlices(&::GraphicsResource.Files, "GammaShader.glsl"); - - // Note that these shader slices are always loaded, even if lighting - // is disabled. The shaders then assume a default light if HAVE_LIGHT - // is not defined. This avoids completely flat shading for meshes - // that are shown as picture graphics for example. - shader.LoadSlices(&::GraphicsResource.Files, "ObjectLightShader.glsl"); - shader.LoadSlices(&::GraphicsResource.Files, "LightShader.glsl"); - shader.LoadSlices(&::GraphicsResource.Files, "AmbientShader.glsl"); - - if (ssc & C4SSC_BASE) shader.LoadSlices(&::GraphicsResource.Files, "SpriteTextureShader.glsl"); - if (ssc & C4SSC_OVERLAY) shader.LoadSlices(&::GraphicsResource.Files, "SpriteOverlayShader.glsl"); + shader.LoadSlices(&::GraphicsResource.Files, "CommonShader.glsl"); + shader.LoadSlices(&::GraphicsResource.Files, "ObjectShader.glsl"); #endif }