reorganized procedural shader code, added getWorldEyeWorldPos(), removed iWorldEyePosition

This commit is contained in:
SamGondelman 2016-06-10 13:42:19 -07:00
parent 8cccd5416a
commit da98ee0916
6 changed files with 16 additions and 408 deletions

View file

@ -1,382 +0,0 @@
//
// Created by Bradley Austin Davis on 2015/09/05
// Copyright 2013-2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Shader includes portions of webgl-noise:
// Description : Array and textureless GLSL 2D/3D/4D simplex
// noise functions.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : ijm
// Lastmod : 20110822 (ijm)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
// https://github.com/ashima/webgl-noise
//
const QString SHADER_COMMON = R"SHADER(
layout(location = 0) out vec4 _fragColor0;
layout(location = 1) out vec4 _fragColor1;
layout(location = 2) out vec4 _fragColor2;
// the alpha threshold
uniform float alphaThreshold;
vec2 signNotZero(vec2 v) {
return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
}
vec2 float32x3_to_oct(in vec3 v) {
vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));
return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);
}
vec3 oct_to_float32x3(in vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
if (v.z < 0) {
v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
}
return normalize(v);
}
vec3 snorm12x2_to_unorm8x3(vec2 f) {
vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));
float t = floor(u.y / 256.0);
return floor(vec3(
u.x / 16.0,
fract(u.x / 16.0) * 256.0 + t,
u.y - t * 256.0
)) / 255.0;
}
vec2 unorm8x3_to_snorm12x2(vec3 u) {
u *= 255.0;
u.y *= (1.0 / 16.0);
vec2 s = vec2( u.x * 16.0 + floor(u.y),
fract(u.y) * (16.0 * 256.0) + u.z);
return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));
}
float mod289(float x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec2 mod289(vec2 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec3 mod289(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 mod289(vec4 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
float permute(float x) {
return mod289(((x*34.0)+1.0)*x);
}
vec3 permute(vec3 x) {
return mod289(((x*34.0)+1.0)*x);
}
vec4 permute(vec4 x) {
return mod289(((x*34.0)+1.0)*x);
}
float taylorInvSqrt(float r) {
return 1.79284291400159 - 0.85373472095314 * r;
}
vec4 taylorInvSqrt(vec4 r) {
return 1.79284291400159 - 0.85373472095314 * r;
}
vec4 grad4(float j, vec4 ip) {
const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
vec4 p, s;
p.xyz = floor(fract(vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
s = vec4(lessThan(p, vec4(0.0)));
p.xyz = p.xyz + (s.xyz * 2.0 - 1.0) * s.www;
return p;
}
// (sqrt(5) - 1)/4 = F4, used once below
#define F4 0.309016994374947451
float snoise(vec4 v) {
const vec4 C = vec4(0.138196601125011, // (5 - sqrt(5))/20 G4
0.276393202250021, // 2 * G4
0.414589803375032, // 3 * G4
-0.447213595499958); // -1 + 4 * G4
// First corner
vec4 i = floor(v + dot(v, vec4(F4)));
vec4 x0 = v - i + dot(i, C.xxxx);
// Other corners
// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
vec4 i0;
vec3 isX = step(x0.yzw, x0.xxx);
vec3 isYZ = step(x0.zww, x0.yyz);
i0.x = isX.x + isX.y + isX.z;
i0.yzw = 1.0 - isX;
i0.y += isYZ.x + isYZ.y;
i0.zw += 1.0 - isYZ.xy;
i0.z += isYZ.z;
i0.w += 1.0 - isYZ.z;
// i0 now contains the unique values 0,1,2,3 in each channel
vec4 i3 = clamp(i0, 0.0, 1.0);
vec4 i2 = clamp(i0 - 1.0, 0.0, 1.0);
vec4 i1 = clamp(i0 - 2.0, 0.0, 1.0);
vec4 x1 = x0 - i1 + C.xxxx;
vec4 x2 = x0 - i2 + C.yyyy;
vec4 x3 = x0 - i3 + C.zzzz;
vec4 x4 = x0 + C.wwww;
// Permutations
i = mod289(i);
float j0 = permute(permute(permute(permute(i.w) + i.z) + i.y) + i.x);
vec4 j1 = permute(
permute(
permute(
permute(i.w + vec4(i1.w, i2.w, i3.w, 1.0)) + i.z
+ vec4(i1.z, i2.z, i3.z, 1.0)) + i.y
+ vec4(i1.y, i2.y, i3.y, 1.0)) + i.x
+ vec4(i1.x, i2.x, i3.x, 1.0));
// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope
// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
vec4 ip = vec4(1.0 / 294.0, 1.0 / 49.0, 1.0 / 7.0, 0.0);
vec4 p0 = grad4(j0, ip);
vec4 p1 = grad4(j1.x, ip);
vec4 p2 = grad4(j1.y, ip);
vec4 p3 = grad4(j1.z, ip);
vec4 p4 = grad4(j1.w, ip);
// Normalise gradients
vec4 norm = taylorInvSqrt(
vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
p4 *= taylorInvSqrt(dot(p4, p4));
// Mix contributions from the five corners
vec3 m0 = max(0.6 - vec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)), 0.0);
vec2 m1 = max(0.6 - vec2(dot(x3, x3), dot(x4, x4)), 0.0);
m0 = m0 * m0;
m1 = m1 * m1;
return 49.0
* (dot(m0 * m0, vec3(dot(p0, x0), dot(p1, x1), dot(p2, x2)))
+ dot(m1 * m1, vec2(dot(p3, x3), dot(p4, x4))));
}
float snoise(vec3 v) {
const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// First corner
vec3 i = floor(v + dot(v, C.yyy));
vec3 x0 = v - i + dot(i, C.xxx);
// Other corners
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min(g.xyz, l.zxy);
vec3 i2 = max(g.xyz, l.zxy);
vec3 x1 = x0 - i1 + C.xxx;
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
i = mod289(i);
vec4 p = permute(
permute(
permute(i.z + vec4(0.0, i1.z, i2.z, 1.0)) + i.y
+ vec4(0.0, i1.y, i2.y, 1.0)) + i.x
+ vec4(0.0, i1.x, i2.x, 1.0));
// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
float n_ = 0.142857142857; // 1.0/7.0
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_); // mod(j,N)
vec4 x = x_ * ns.x + ns.yyyy;
vec4 y = y_ * ns.x + ns.yyyy;
vec4 h = 1.0 - abs(x) - abs(y);
vec4 b0 = vec4(x.xy, y.xy);
vec4 b1 = vec4(x.zw, y.zw);
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
vec4 s0 = floor(b0) * 2.0 + 1.0;
vec4 s1 = floor(b1) * 2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
vec3 p0 = vec3(a0.xy, h.x);
vec3 p1 = vec3(a0.zw, h.y);
vec3 p2 = vec3(a1.xy, h.z);
vec3 p3 = vec3(a1.zw, h.w);
//Normalise gradients
vec4 norm = taylorInvSqrt(
vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)),
0.0);
m = m * m;
return 42.0
* dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
}
float snoise(vec2 v) {
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
-0.577350269189626, // -1.0 + 2.0 * C.x
0.024390243902439); // 1.0 / 41.0
// First corner
vec2 i = floor(v + dot(v, C.yy));
vec2 x0 = v - i + dot(i, C.xx);
// Other corners
vec2 i1;
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
vec4 x12 = x0.xyxy + C.xxzz;
x12.xy -= i1;
// Permutations
i = mod289(i); // Avoid truncation effects in permutation
vec3 p = permute(
permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));
vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)),
0.0);
m = m * m;
m = m * m;
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
// Normalise gradients implicitly by scaling m
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);
// Compute final noise value at P
vec3 g;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
}
// the interpolated normal
in vec3 _normal;
in vec3 _color;
in vec2 _texCoord0;
in vec4 _position;
// TODO add more uniforms
uniform float iGlobalTime; // shader playback time (in seconds)
uniform vec3 iWorldScale; // the dimensions of the object being rendered
uniform mat3 iWorldOrientation; // the orientation of the object being rendered
uniform vec3 iWorldEyePosition; // the world position of the eye
// TODO add support for textures
// TODO document available inputs other than the uniforms
// TODO provide world scale in addition to the untransformed position
const vec3 DEFAULT_SPECULAR = vec3(0.1);
const float DEFAULT_SHININESS = 10;
)SHADER";
// V1 shaders, only support emissive
// vec4 getProceduralColor()
const QString SHADER_TEMPLATE_V1 = SHADER_COMMON + R"SCRIBE(
#line 1001
%1
#line 317
void main(void) {
vec4 emissive = getProceduralColor();
float alpha = emissive.a;
if (alpha != 1.0) {
discard;
}
vec4 diffuse = vec4(_color.rgb, alpha);
vec4 normal = vec4(packNormal(normalize(_normal)), 0.5);
_fragColor0 = diffuse;
_fragColor1 = normal;
_fragColor2 = vec4(emissive.rgb, DEFAULT_SHININESS / 128.0);
}
)SCRIBE";
// void getProceduralDiffuseAndEmissive(out vec4 diffuse, out vec4 emissive)
const QString SHADER_TEMPLATE_V2 = SHADER_COMMON + R"SCRIBE(
// FIXME should we be doing the swizzle here?
vec3 iResolution = iWorldScale.xzy;
// FIXME Mouse X,Y coordinates, and Z,W are for the click position if clicked (not supported in High Fidelity at the moment)
vec4 iMouse = vec4(0);
// FIXME We set the seconds (iDate.w) of iDate to iGlobalTime, which contains the current date in seconds
vec4 iDate = vec4(0, 0, 0, iGlobalTime);
#line 1001
%1
#line 351
void main(void) {
vec3 diffuse = _color.rgb;
vec3 specular = DEFAULT_SPECULAR;
float shininess = DEFAULT_SHININESS;
float emissiveAmount = getProceduralColors(diffuse, specular, shininess);
_fragColor0 = vec4(diffuse.rgb, 1.0);
_fragColor1 = vec4(packNormal(normalize(_normal.xyz)), 1.0 - (emissiveAmount / 2.0));
_fragColor2 = vec4(specular, shininess / 128.0);
}
)SCRIBE";

View file

@ -27,6 +27,10 @@ layout(std140) uniform transformCameraBuffer {
TransformCamera getTransformCamera() {
return _camera;
}
vec3 getEyeWorldPos() {
return _camera._viewInverse[3].xyz;
}
<@endfunc@>

View file

@ -19,7 +19,7 @@
#include <NumericalConstants.h>
#include <GLMHelpers.h>
#include "ProceduralShaders.h"
#include "ProceduralCommon_frag.h"
// Userdata parsing constants
static const QString PROCEDURAL_USER_DATA_KEY = "ProceduralEntity";
@ -40,7 +40,6 @@ static const std::string STANDARD_UNIFORM_NAMES[Procedural::NUM_STANDARD_UNIFORM
"iWorldScale",
"iWorldPosition",
"iWorldOrientation",
"iWorldEyePosition",
"iChannelResolution"
};
@ -231,7 +230,7 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm
std::string fragmentShaderSource = _fragmentSource;
size_t replaceIndex = fragmentShaderSource.find(PROCEDURAL_COMMON_BLOCK);
if (replaceIndex != std::string::npos) {
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_COMMON_BLOCK.size(), SHADER_COMMON);
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_COMMON_BLOCK.size(), ProceduralCommon_frag);
}
replaceIndex = fragmentShaderSource.find(PROCEDURAL_VERSION);
@ -421,14 +420,6 @@ void Procedural::setupUniforms() {
batch._glUniform(_standardUniformSlots[POSITION], _entityPosition);
});
}
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[EYE_POSITION]) {
// FIXME move into the 'set once' section, since this doesn't change over time
_uniforms.push_back([=](gpu::Batch& batch) {
batch._glUniform(_standardUniformSlots[EYE_POSITION], _eyePos);
});
}
}
void Procedural::setupChannels(bool shouldCreate) {

View file

@ -57,7 +57,6 @@ public:
SCALE,
POSITION,
ORIENTATION,
EYE_POSITION,
CHANNEL_RESOLUTION,
NUM_STANDARD_UNIFORMS
};

View file

@ -1,3 +1,5 @@
<@include gpu/Config.slh@>
// Generated on <$_SCRIBE_DATE$>
//
// Created by Bradley Austin Davis on 2015/09/05
// Copyright 2013-2015 High Fidelity, Inc.
@ -17,8 +19,8 @@
// https://github.com/ashima/webgl-noise
//
const std::string SHADER_COMMON = R"SHADER(
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
float mod289(float x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
@ -262,11 +264,6 @@ float snoise(vec2 v) {
return 130.0 * dot(m, g);
}
// shader playback time (in seconds)
uniform float iGlobalTime;
// the dimensions of the object being rendered
uniform vec3 iWorldScale;
#define PROCEDURAL 1
//PROCEDURAL_VERSION
@ -286,17 +283,16 @@ const float iSampleRate = 1.0;
const vec4 iChannelTime = vec4(0.0);
uniform float iGlobalTime; // shader playback time (in seconds)
uniform vec4 iDate;
uniform int iFrameCount;
uniform vec3 iWorldPosition;
uniform mat3 iWorldOrientation;
uniform vec3 iWorldEyePosition;
uniform vec3 iWorldPosition; // the position of the object being rendered
uniform vec3 iWorldScale; // the dimensions of the object being rendered
uniform mat3 iWorldOrientation; // the orientation of the object being rendered
uniform vec3 iChannelResolution[4];
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform sampler2D iChannel2;
uniform sampler2D iChannel3;
#endif
)SHADER";
#endif

View file

@ -52,7 +52,7 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum,
batch.setModelTransform(Transform()); // only for Mac
auto& procedural = skybox._procedural;
procedural.prepare(batch, glm::vec3(0), glm::vec3(1), glm::quat(1, 0, 0, 0), glm::vec3(0));
procedural.prepare(batch, glm::vec3(0), glm::vec3(1), glm::quat(), glm::vec3(0));
auto textureSlot = procedural.getShader()->getTextures().findLocation("cubeMap");
auto bufferSlot = procedural.getShader()->getBuffers().findLocation("skyboxBuffer");
skybox.prepare(batch, textureSlot, bufferSlot);