First waters.

This commit is contained in:
Lubos Lenco 2016-05-05 19:50:03 +02:00
parent afc4ac293b
commit f9604b5bb6
24 changed files with 1047 additions and 90 deletions

View file

@ -0,0 +1,25 @@
package cycles.renderpipeline;
import lue.node.RenderPipeline;
class FFT {
static var firstFrame = true;
// public static function init() {
// var res = 512;
// var phaseArray = new haxe.io.Float32Array(res * res * 4);
// for (i in 0...res) {
// for (j in 0...res) {
// phaseArray[i * res * 4 + j * 4] = Math.random() * 2.0 * Math.PI;
// phaseArray[i * res * 4 + j * 4 + 1] = 0;
// phaseArray[i * res * 4 + j * 4 + 2] = 0;
// phaseArray[i * res * 4 + j * 4 + 3] = 0;
// }
// }
// }
public static function run(pipe:RenderPipeline) {
}
}

View file

@ -127,8 +127,10 @@ class FirstPersonController extends Trait {
var force = new Vec4(0, 0, -1);
force.applyProjection(mat);
force = force.mult(Time.delta * 3000 / 2);
body.applyImpulse(force);
// body.applyImpulse(force);
var btvec = body.getLinearVelocity();
body.setLinearVelocity(0.0, 0.0, btvec.z() - 1.0);
}
else {
body.activate();

View file

@ -206,9 +206,9 @@ class RigidBody extends Trait {
body.ptr.setAngularFactor(BtVector3.create(x, y, z).value);
}
// public function getLinearVelocity():BtVector3 {
// return body.ptr.getLinearVelocity(); // Unable to compile in cpp
// }
public function getLinearVelocity():BtVector3 {
return body.ptr.getLinearVelocity(); // Unable to compile in cpp
}
public function setLinearVelocity(x:Float, y:Float, z:Float) {
body.ptr.setLinearVelocity(BtVector3.create(x, y, z).value);

View file

@ -2083,22 +2083,22 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
# Rigid body trait
if node.rigid_body != None:
rb = node.rigid_body
shape = '0' # BOX
shape = 0 # BOX
if rb.collision_shape == 'SPHERE':
shape = '1'
shape = 1
elif rb.collision_shape == 'CONVEX_HULL':
shape = '2'
shape = 2
elif rb.collision_shape == 'MESH':
if rb.enabled:
shape = '3' # Mesh
shape = 3 # Mesh
else:
shape = '8' # Static Mesh
shape = 8 # Static Mesh
elif rb.collision_shape == 'CONE':
shape = '4'
shape = 4
elif rb.collision_shape == 'CYLINDER':
shape = '5'
shape = 5
elif rb.collision_shape == 'CAPSULE':
shape = '6'
shape = 6
body_mass = 0
if rb.enabled:
body_mass = rb.mass

View file

@ -200,6 +200,61 @@ class DrawQuadNode(Node, CGPipelineTreeNode):
def free(self):
print("Removing node ", self, ", Goodbye!")
class CallFunctionNode(Node, CGPipelineTreeNode):
'''A custom node'''
bl_idname = 'CallFunctionNodeType'
bl_label = 'Call Function'
bl_icon = 'SOUND'
def init(self, context):
self.inputs.new('NodeSocketShader', "Stage")
self.inputs.new('NodeSocketString', "Function")
self.outputs.new('NodeSocketShader', "Stage")
def copy(self, node):
print("Copying from node ", node)
def free(self):
print("Removing node ", self, ", Goodbye!")
class BranchFunctionNode(Node, CGPipelineTreeNode):
'''A custom node'''
bl_idname = 'BranchFunctionNodeType'
bl_label = 'Branch Function'
bl_icon = 'SOUND'
def init(self, context):
self.inputs.new('NodeSocketShader', "Stage")
self.inputs.new('NodeSocketString', "Function")
self.outputs.new('NodeSocketShader', "True")
self.outputs.new('NodeSocketShader', "False")
def copy(self, node):
print("Copying from node ", node)
def free(self):
print("Removing node ", self, ", Goodbye!")
class MergeStagesNode(Node, CGPipelineTreeNode):
'''A custom node'''
bl_idname = 'MergeStagesNodeType'
bl_label = 'Merge Stages'
bl_icon = 'SOUND'
def init(self, context):
self.inputs.new('NodeSocketShader', "Stage")
self.inputs.new('NodeSocketShader', "Stage")
self.outputs.new('NodeSocketShader', "Stage")
def copy(self, node):
print("Copying from node ", node)
def free(self):
print("Removing node ", self, ", Goodbye!")
class DrawWorldNode(Node, CGPipelineTreeNode):
'''A custom node'''
@ -284,6 +339,11 @@ class MyConstantNodeCategory(NodeCategory):
def poll(cls, context):
return context.space_data.tree_type == 'CGPipelineTreeType'
class MyLogicNodeCategory(NodeCategory):
@classmethod
def poll(cls, context):
return context.space_data.tree_type == 'CGPipelineTreeType'
node_categories = [
MyPipelineNodeCategory("PIPELINENODES", "Pipeline", items=[
NodeItem("BeginNodeType"),
@ -304,6 +364,11 @@ node_categories = [
MyConstantNodeCategory("CONSTANTNODES", "Constant", items=[
NodeItem("ScreenNodeType"),
]),
MyLogicNodeCategory("LOGICNODES", "Logic", items=[
NodeItem("CallFunctionNodeType"),
NodeItem("BranchFunctionNodeType"),
NodeItem("MergeStagesNodeType"),
]),
]
@ -387,7 +452,7 @@ def buildNodeTree(node_group, shader_references, asset_references):
# Used to merge bind target nodes into one stage
last_bind_target = None
buildNode(res, rn, node_group, last_bind_target, shader_references, asset_references)
buildNode(res.stages, rn, node_group, last_bind_target, shader_references, asset_references)
with open(path + node_group_name + '.json', 'w') as f:
f.write(output.to_JSON())
@ -397,37 +462,11 @@ def make_set_target(stage, node_group, node, target_index=1, color_buffer_index=
targetNode = findNodeByLink(node_group, node, node.inputs[target_index])
if targetNode.bl_idname == 'TargetNodeType':
cb_postfix = ''
if color_buffer_index >= 0 and targetNode.inputs[3].default_value > 1: # MRT target, bind only specified target
cb_postfix = str(color_buffer_index)
postfix = ''
if targetNode.inputs[7].default_value == True:
if make_set_target.is_last_target_pong == True:
make_set_target.is_last_two_targets_pong = True
make_set_target.pong = not make_set_target.pong
else:
make_set_target.is_last_two_targets_pong = False
make_set_target.last_pong_target_pong = make_set_target.pong
if make_set_target.pong == True:
postfix = '_pong'
make_set_target.is_last_target_pong = True
else:
if make_set_target.is_last_two_targets_pong == True:
make_set_target.pong = not make_set_target.pong
make_set_target.is_last_target_pong = False
if make_set_target.is_last_two_targets_pong == True:
make_set_target.is_last_two_chain_broken = True
make_set_target.is_last_two_targets_pong = False
targetId = targetNode.inputs[0].default_value + cb_postfix + postfix
targetId = targetNode.inputs[0].default_value + cb_postfix
elif targetNode.bl_idname == 'ColorBufferNodeType':
cb_index = targetNode.inputs[1].default_value
@ -439,17 +478,9 @@ def make_set_target(stage, node_group, node, target_index=1, color_buffer_index=
return
else: # Framebuffer
if make_set_target.is_last_two_targets_pong == True:
make_set_target.pong = not make_set_target.pong
make_set_target.is_last_two_targets_pong = False
targetId = ''
stage.params.append(targetId)
make_set_target.pong = False
make_set_target.is_last_target_pong = False
make_set_target.is_last_two_targets_pong = False
make_set_target.is_last_two_chain_broken = False
make_set_target.last_pong_target_pong = False
def make_clear_target(stage, node_group, node):
stage.command = 'clear_target'
@ -477,20 +508,10 @@ def make_bind_target(stage, node_group, node, target_index=1, constant_index=2,
if targetNode.bl_idname == 'TargetNodeType':
cb_postfix = ''
if color_buffer_index >= 0 and targetNode.inputs[3].default_value > 1: # MRT target, bind only specified target
cb_postfix = str(color_buffer_index)
postfix = ''
if targetNode.inputs[7].default_value == True:
if make_set_target.is_last_target_pong == False:
if make_set_target.last_pong_target_pong == True:
postfix = '_pong'
elif make_set_target.pong == False:
postfix = '_pong'
targetId = targetNode.inputs[0].default_value + cb_postfix + postfix
targetId = targetNode.inputs[0].default_value + cb_postfix
stage.params.append(targetId)
stage.params.append(node.inputs[constant_index].default_value)
@ -518,13 +539,40 @@ def make_draw_world(stage, node_group, node):
wname = bpy.data.worlds[0].name
stage.params.append(wname + '_material/' + wname + '_material/env_map') # Only one world for now
def buildNode(res, node, node_group, last_bind_target, shader_references, asset_references):
def make_call_function(stage, node_group, node):
stage.command = 'call_function'
stage.params.append(node.inputs[1].default_value)
def make_branch_function(stage, node_group, node):
make_call_function(stage, node_group, node)
def process_call_function(stage, stages, node, node_group, last_bind_target, shader_references, asset_references):
# Step till merge node
stage.returns_true = []
if node.outputs[0].is_linked:
stageNode = findNodeByLinkFrom(node_group, node, node.outputs[0])
buildNode(stage.returns_true, stageNode, node_group, last_bind_target, shader_references, asset_references)
stage.returns_false = []
if node.outputs[1].is_linked:
stageNode = findNodeByLinkFrom(node_group, node, node.outputs[1])
margeNode = buildNode(stage.returns_false, stageNode, node_group, last_bind_target, shader_references, asset_references)
# Continue using top level stages after merge node
afterMergeNode = findNodeByLinkFrom(node_group, margeNode, margeNode.outputs[0])
buildNode(stages, afterMergeNode, node_group, last_bind_target, shader_references, asset_references)
# Returns merge node
def buildNode(stages, node, node_group, last_bind_target, shader_references, asset_references):
stage = Object()
stage.params = []
append_stage = True
if node.bl_idname == 'SetTargetNodeType':
if node.bl_idname == 'MergeStagesNodeType':
return node
elif node.bl_idname == 'SetTargetNodeType':
last_bind_target = None
make_set_target(stage, node_group, node)
@ -549,6 +597,15 @@ def buildNode(res, node, node_group, last_bind_target, shader_references, asset_
elif node.bl_idname == 'DrawWorldNodeType':
make_draw_world(stage, node_group, node)
elif node.bl_idname == 'BranchFunctionNodeType':
make_branch_function(stage, node_group, node)
stages.append(stage)
process_call_function(stage, stages, node, node_group, last_bind_target, shader_references, asset_references)
return
elif node.bl_idname == 'CallFunctionNodeType':
make_call_function(stage, node_group, node)
elif node.bl_idname == 'QuadPassNodeType':
append_stage = False
@ -556,7 +613,7 @@ def buildNode(res, node, node_group, last_bind_target, shader_references, asset_
if node.inputs[1].is_linked:
last_bind_target = None
make_set_target(stage, node_group, node)
res.stages.append(stage)
stages.append(stage)
# Bind targets
stage = Object()
stage.params = []
@ -573,20 +630,20 @@ def buildNode(res, node, node_group, last_bind_target, shader_references, asset_
bind_target_used = True
make_bind_target(stage, node_group, node, target_index=7, constant_index=8)
if bind_target_used:
res.stages.append(stage)
stages.append(stage)
stage = Object()
stage.params = []
# Draw quad
make_draw_quad(stage, node_group, node, shader_references, asset_references, context_index=2)
res.stages.append(stage)
stages.append(stage)
if append_stage:
res.stages.append(stage)
stages.append(stage)
# Build next stage
if node.outputs[0].is_linked:
stageNode = findNodeByLinkFrom(node_group, node, node.outputs[0])
buildNode(res, stageNode, node_group, last_bind_target, shader_references, asset_references)
buildNode(stages, stageNode, node_group, last_bind_target, shader_references, asset_references)
def findNodeByLink(node_group, to_node, inp):
for link in node_group.links:
@ -613,6 +670,7 @@ def make_render_target(n, postfix=''):
target.depth_buffer = n.inputs[4].default_value
target.stencil_buffer = n.inputs[5].default_value
target.format = n.inputs[6].default_value
target.ping_pong = n.inputs[7].default_value
return target
def get_render_targets(node_group):
@ -621,7 +679,4 @@ def get_render_targets(node_group):
if n.bl_idname == 'TargetNodeType':
target = make_render_target(n)
render_targets.append(target)
if n.inputs[7].default_value == True: # Ping-pong
target = make_render_target(n, '_pong')
render_targets.append(target)
return render_targets

View file

@ -58,6 +58,7 @@ class Main {
public static function main() {
lue.sys.CompileTime.importPackage('lue.trait');
lue.sys.CompileTime.importPackage('cycles.trait');
lue.sys.CompileTime.importPackage('cycles.renderpipeline');
lue.sys.CompileTime.importPackage('""" + bpy.data.worlds[0]['CGProjectPackage'] + """');
#if (js && WITH_PHYSICS)
untyped __js__("

View file

@ -59,6 +59,10 @@ os.chdir('../sss_pass')
make_resources.make('sss_pass.shader.json')
make_variants.make('sss_pass.shader.json')
os.chdir('../water_pass')
make_resources.make('water_pass.shader.json')
make_variants.make('water_pass.shader.json')
# os.chdir('../pt_trace_pass')
# make_resources.make('pt_trace_pass.shader.json')
# make_variants.make('pt_trace_pass.shader.json')

View file

@ -162,17 +162,17 @@ void main() {
vec4 col = texture(tex, uv);
// Blur
// float depth = texture(gbuffer0, texCoord).a;
// float blur_amount = abs(depth - focus_depth);
// if (depth < depth - focus_depth) {
// blur_amount *= 10.0;
// }
// blur_amount = clamp(blur_amount, 0.0, 1.0);
// vec4 baseColor = col;//texture(tex, texCoord);
// vec4 blurredColor = vec4(0.0, 0.0, 0.0, 0.0);
// float blurSize = 0.005 * blur_amount;
// blurredColor = 0.75 * sampleBox(blurSize * 0.5) + 0.25 * sampleBox(blurSize * 1.0);
// col = baseColor * (1.0 - blur_amount) + blurredColor * blur_amount;
float depth = texture(gbuffer0, texCoord).a;
float blur_amount = abs(depth - focus_depth);
if (depth < depth - focus_depth) {
blur_amount *= 10.0;
}
blur_amount = clamp(blur_amount, 0.0, 1.0);
vec4 baseColor = col;//texture(tex, texCoord);
vec4 blurredColor = vec4(0.0, 0.0, 0.0, 0.0);
float blurSize = 0.005 * blur_amount;
blurredColor = 0.75 * sampleBox(blurSize * 0.5) + 0.25 * sampleBox(blurSize * 1.0);
col = baseColor * (1.0 - blur_amount) + blurredColor * blur_amount;
// Fog
// vec3 pos = texture(gbuffer1, texCoord).rgb;

View file

@ -185,12 +185,11 @@ vec2 unpackFloat(float f) {
}
void main() {
vec4 g0 = texture(gbuffer0, texCoord); // Normals, depth
vec4 g0 = texture(gbuffer0, texCoord); // Normal.xy, mask, depth
float depth = 1.0 - g0.a;
if (depth == 0.0) discard;
vec4 g1 = texture(gbuffer1, texCoord); // Base color, roughness
vec4 g2 = texture(gbuffer2, texCoord); // 0,0,0, metalness
vec4 g1 = texture(gbuffer1, texCoord); // Base color.rgb, roughn/met
float ao = texture(ssaotex, texCoord).r;
vec2 enc = g0.rg;
@ -204,7 +203,6 @@ void main() {
vec2 roughmet = unpackFloat(g1.a);
float roughness = roughmet.x;
float metalness = roughmet.y;
// float occlusion = g2.a;
vec3 lightDir = light - p.xyz;
vec3 eyeDir = eye - p.xyz;
@ -239,12 +237,13 @@ void main() {
// Indirect
vec3 indirectDiffuse = texture(senvmapIrradiance, envMapEquirect(n)).rgb;
indirectDiffuse = pow(indirectDiffuse, vec3(2.2)) * albedo;
// indirectDiffuse = pow(indirectDiffuse, vec3(2.2));
indirectDiffuse *= albedo;
vec3 reflectionWorld = reflect(-v, n);
float lod = getMipLevelFromRoughness(roughness);// + 1.0;
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
prefilteredColor = pow(prefilteredColor, vec3(2.2));
// prefilteredColor = pow(prefilteredColor, vec3(2.2));
vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;
vec3 indirectSpecular = prefilteredColor * (f0 * envBRDF.x + envBRDF.y);

View file

@ -25,6 +25,6 @@ void main() {
// }
vec3 n = normalize(normal);
// gl_FragColor = texture(envmap, envMapEquirect(n));
gl_FragColor = vec4(pow(texture(envmap, envMapEquirect(n)).rgb, vec3(2.2)), 1.0);
gl_FragColor = texture(envmap, envMapEquirect(n));
// gl_FragColor = vec4(pow(texture(envmap, envMapEquirect(n)).rgb, vec3(2.2)), 1.0);
}

View file

@ -42,7 +42,6 @@ precision mediump float;
#endif
uniform sampler2D gbuffer0;
uniform sampler2D gbuffer1;
uniform sampler2D tex;
uniform vec2 dir;

View file

@ -0,0 +1,79 @@
// Based on work by David Li(http://david.li/waves)
#version 450
#ifdef GL_ES
precision mediump float;
#endif
in vec2 texCoord;
const float PI = 3.14159265359;
const float G = 9.81;
const float KM = 370.0;
const float CM = 0.23;
const vec2 wind = vec2(10.0, 10.0);
const float resolution = 512.0;
const float size = 250.0;
float square(float x) {
return x * x;
}
float omega(float k) {
return sqrt(G * k * (1.0 + square(k / KM)));
}
float tanh(float x) {
return (1.0 - exp(-2.0 * x)) / (1.0 + exp(-2.0 * x));
}
void main() {
vec2 coordinates = texCoord.xy * resolution;//gl_FragCoord.xy - 0.5;
float n = (coordinates.x < resolution * 0.5) ? coordinates.x : coordinates.x - resolution;
float m = (coordinates.y < resolution * 0.5) ? coordinates.y : coordinates.y - resolution;
vec2 K = (2.0 * PI * vec2(n, m)) / size;
float k = length(K);
float l_wind = length(wind);
float Omega = 0.84;
float kp = G * square(Omega / l_wind);
float c = omega(k) / k;
float cp = omega(kp) / kp;
float Lpm = exp(-1.25 * square(kp / k));
float gamma = 1.7;
float sigma = 0.08 * (1.0 + 4.0 * pow(Omega, -3.0));
float Gamma = exp(-square(sqrt(k / kp) - 1.0) / 2.0 * square(sigma));
float Jp = pow(gamma, Gamma);
float Fp = Lpm * Jp * exp(-Omega / sqrt(10.0) * (sqrt(k / kp) - 1.0));
float alphap = 0.006 * sqrt(Omega);
float Bl = 0.5 * alphap * cp / c * Fp;
float z0 = 0.000037 * square(l_wind) / G * pow(l_wind / cp, 0.9);
float uStar = 0.41 * l_wind / log(10.0 / z0);
float alpham = 0.01 * ((uStar < CM) ? (1.0 + log(uStar / CM)) : (1.0 + 3.0 * log(uStar / CM)));
float Fm = exp(-0.25 * square(k / KM - 1.0));
float Bh = 0.5 * alpham * CM / c * Fm * Lpm;
float a0 = log(2.0) / 4.0;
float am = 0.13 * uStar / CM;
float Delta = tanh(a0 + 4.0 * pow(c / cp, 2.5) + am * pow(CM / c, 2.5));
float cosPhi = dot(normalize(wind), normalize(K));
float S = (1.0 / (2.0 * PI)) * pow(k, -4.0) * (Bl + Bh) * (1.0 + Delta * (2.0 * cosPhi * cosPhi - 1.0));
float dk = 2.0 * PI / size;
float h = sqrt(S / 2.0) * dk;
if (K.x == 0.0 && K.y == 0.0) {
h = 0.0; //no DC term
}
gl_FragColor = vec4(h, 0.0, 0.0, 0.0);
}

View file

@ -0,0 +1,18 @@
#version 450
#ifdef GL_ES
precision highp float;
#endif
in vec2 pos;
out vec2 texCoord;
const vec2 madd = vec2(0.5, 0.5);
void main() {
// Scale vertex attribute to [0-1] range
texCoord = pos.xy * madd + madd;
gl_Position = vec4(pos.xy, 0.0, 1.0);
}

View file

@ -0,0 +1,30 @@
// Based on work by David Li(http://david.li/waves)
#version 450
#ifdef GL_ES
precision mediump float;
#endif
in vec2 texCoord;
uniform sampler2D texDisplacement;
const float resolution = 512.0;
const float size = 250.0;
void main() {
float texel = 1.0 / resolution;
float texelSize = size / resolution;
vec3 center = texture(texDisplacement, texCoord).rgb;
vec3 right = vec3(texelSize, 0.0, 0.0) + texture(texDisplacement, texCoord + vec2(texel, 0.0)).rgb - center;
vec3 left = vec3(-texelSize, 0.0, 0.0) + texture(texDisplacement, texCoord + vec2(-texel, 0.0)).rgb - center;
vec3 top = vec3(0.0, 0.0, -texelSize) + texture(texDisplacement, texCoord + vec2(0.0, -texel)).rgb - center;
vec3 bottom = vec3(0.0, 0.0, texelSize) + texture(texDisplacement, texCoord + vec2(0.0, texel)).rgb - center;
vec3 topRight = cross(right, top);
vec3 topLeft = cross(top, left);
vec3 bottomLeft = cross(left, bottom);
vec3 bottomRight = cross(bottom, right);
gl_FragColor = vec4(normalize(topRight + topLeft + bottomLeft + bottomRight), 1.0);
}

View file

@ -0,0 +1,18 @@
#version 450
#ifdef GL_ES
precision highp float;
#endif
in vec2 pos;
out vec2 texCoord;
const vec2 madd = vec2(0.5, 0.5);
void main() {
// Scale vertex attribute to [0-1] range
texCoord = pos.xy * madd + madd;
gl_Position = vec4(pos.xy, 0.0, 1.0);
}

View file

@ -0,0 +1,453 @@
// Deferred water based on shader by Wojciech Toman
// http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/rendering-water-as-a-post-process-effect-r2642
// Seascape https://www.shadertoy.com/view/Ms2SD1
// Caustics https://www.shadertoy.com/view/4ljXWh
// Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
#version 450
#ifdef GL_ES
precision mediump float;
#endif
const float PI = 3.1415926535;
const float TwoPI = (2.0 * PI);
uniform sampler2D gbuffer0;
uniform sampler2D tex;
uniform sampler2D senvmapRadiance;
uniform float time;
uniform vec3 eye;
uniform vec3 eyeLook;
uniform vec3 light;
in vec2 texCoord;
in vec3 viewRay;
const float timeScale = 1000.0;
const float waterLevel = 0.0;
const float fadeSpeed = 0.15;
const float maxAmplitude = 2.5;
const vec3 sunColor = vec3(1.0, 1.0, 1.0);
const float shoreHardness = 1.0;
const float refractionStrength = 0.0;
const vec3 foamExistence = vec3(0.65, 1.35, 0.5);
const float sunScale = 3.0;
const float shininess = 0.7;
const float specular_intensity = 0.32;
const vec3 depthColour = vec3(0.0078, 0.5176, 0.9);
const vec3 bigDepthColour = vec3(0.0039, 0.00196, 0.345);
const vec3 extinction = vec3(7.0, 30.0, 40.0); // Horizontal
const float visibility = 2.0;
const vec2 scale = vec2(0.005, 0.005);
const float refractionScale = 0.005;
const vec2 wind = vec2(-0.3, 0.7);
const float SEA_HEIGHT = 0.6;
const float SEA_CHOPPY = 4.0;
const float SEA_SPEED = 1.0;
const float SEA_FREQ = 0.16;
// const vec3 SEA_BASE = vec3(0.1,0.19,0.22);
const vec3 SEA_BASE = vec3(0.1,0.19,0.37);
// const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6);
const vec3 SEA_WATER_COLOR = vec3(0.6,0.7,0.9);
const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
vec2 envMapEquirect(vec3 normal) {
float phi = acos(normal.z);
float theta = atan(-normal.y, normal.x) + PI;
return vec2(theta / TwoPI, phi / PI);
}
float hash( vec2 p ) {
float h = dot(p,vec2(127.1,311.7));
return fract(sin(h)*43758.5453123);
}
float noise( vec2 p ) {
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return -1.0+2.0*mix(
mix( hash( i + vec2(0.0,0.0) ),
hash( i + vec2(1.0,0.0) ), u.x),
mix( hash( i + vec2(0.0,1.0) ),
hash( i + vec2(1.0,1.0) ), u.x), u.y);
}
float sea_octave(vec2 uv, float choppy) {
uv += noise(uv);
vec2 wv = 1.0-abs(sin(uv));
vec2 swv = abs(cos(uv));
wv = mix(wv,swv,wv);
return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
}
float map(vec3 p) {
float freq = SEA_FREQ;
float amp = SEA_HEIGHT;
float choppy = SEA_CHOPPY;
vec2 uv = p.xy;
uv.x *= 0.75;
float d, h = 0.0;
// for(int i = 0; i < 2; i++) {
d = sea_octave((uv+(time * SEA_SPEED))*freq,choppy);
d += sea_octave((uv-(time * SEA_SPEED))*freq,choppy);
h += d * amp;
uv *= octave_m; freq *= 1.9; amp *= 0.22;
choppy = mix(choppy,1.0,0.2);
//
d = sea_octave((uv+(time * SEA_SPEED))*freq,choppy);
d += sea_octave((uv-(time * SEA_SPEED))*freq,choppy);
h += d * amp;
uv *= octave_m; freq *= 1.9; amp *= 0.22;
choppy = mix(choppy,1.0,0.2);
//
// }
return p.z - h;
}
float map_detailed(vec3 p) {
float freq = SEA_FREQ;
float amp = SEA_HEIGHT;
float choppy = SEA_CHOPPY;
vec2 uv = p.xy; uv.x *= 0.75;
float d, h = 0.0;
// for(int i = 0; i < 4; i++) {
d = sea_octave((uv+(time * SEA_SPEED))*freq,choppy);
d += sea_octave((uv-(time * SEA_SPEED))*freq,choppy);
h += d * amp;
uv *= octave_m; freq *= 1.9; amp *= 0.22;
choppy = mix(choppy,1.0,0.2);
//
d = sea_octave((uv+(time * SEA_SPEED))*freq,choppy);
d += sea_octave((uv-(time * SEA_SPEED))*freq,choppy);
h += d * amp;
uv *= octave_m; freq *= 1.9; amp *= 0.22;
choppy = mix(choppy,1.0,0.2);
d = sea_octave((uv+(time * SEA_SPEED))*freq,choppy);
d += sea_octave((uv-(time * SEA_SPEED))*freq,choppy);
h += d * amp;
uv *= octave_m; freq *= 1.9; amp *= 0.22;
choppy = mix(choppy,1.0,0.2);
d = sea_octave((uv+(time * SEA_SPEED))*freq,choppy);
d += sea_octave((uv-(time * SEA_SPEED))*freq,choppy);
h += d * amp;
uv *= octave_m; freq *= 1.9; amp *= 0.22;
choppy = mix(choppy,1.0,0.2);
d = sea_octave((uv+(time * SEA_SPEED))*freq,choppy);
d += sea_octave((uv-(time * SEA_SPEED))*freq,choppy);
h += d * amp;
uv *= octave_m; freq *= 1.9; amp *= 0.22;
choppy = mix(choppy,1.0,0.2);
// }
return p.z - h;
}
vec3 getNormal(vec3 p, float eps) {
vec3 n;
n.z = map_detailed(p);
n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.z;
n.y = map_detailed(vec3(p.x,p.y+eps,p.z)) - n.z;
n.z = eps;
return normalize(n);
}
vec3 heightMapTracing(vec3 ori, vec3 dir) {
vec3 p;
float tm = 0.0;
float tx = 1000.0;
float hx = map_detailed(ori + dir * tx);
if(hx > 0.0) return p;
float hm = map_detailed(ori + dir * tm);
float tmid = 0.0;
// for(int i = 0; i < 5; i++) {
tmid = mix(tm,tx, hm/(hm-hx));
p = ori + dir * tmid;
float hmid = map_detailed(p);
if(hmid < 0.0) {
tx = tmid;
hx = hmid;
} else {
tm = tmid;
hm = hmid;
}
//
tmid = mix(tm,tx, hm/(hm-hx));
p = ori + dir * tmid;
hmid = map_detailed(p);
if(hmid < 0.0) {
tx = tmid;
hx = hmid;
} else {
tm = tmid;
hm = hmid;
}
tmid = mix(tm,tx, hm/(hm-hx));
p = ori + dir * tmid;
hmid = map_detailed(p);
if(hmid < 0.0) {
tx = tmid;
hx = hmid;
} else {
tm = tmid;
hm = hmid;
}
tmid = mix(tm,tx, hm/(hm-hx));
p = ori + dir * tmid;
hmid = map_detailed(p);
if(hmid < 0.0) {
tx = tmid;
hx = hmid;
} else {
tm = tmid;
hm = hmid;
}
tmid = mix(tm,tx, hm/(hm-hx));
p = ori + dir * tmid;
hmid = map_detailed(p);
if(hmid < 0.0) {
tx = tmid;
hx = hmid;
} else {
tm = tmid;
hm = hmid;
}
// }
return p;
}
vec3 getSkyColor(vec3 e) {
e.z = max(e.z,0.0);
vec3 ret;
ret.x = pow(1.0-e.z,2.0);
ret.z = 1.0-e.z;
ret.y = 0.6+(1.0-e.z)*0.4;
return ret;
}
float diffuse(vec3 n,vec3 l,float p) {
return pow(dot(n,l) * 0.4 + 0.6,p);
}
float specular(vec3 n,vec3 l,vec3 e,float s) {
float nrm = (s + 8.0) / (3.1415 * 8.0);
return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
}
vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {
float fresnel = 1.0 - max(dot(n,-eye),0.0);
fresnel = pow(fresnel,3.0) * 0.65;
vec3 reflected = getSkyColor(reflect(eye,n));
// vec3 reflected = textureLod(senvmapRadiance, envMapEquirect(reflect(eye,n)), 1.0).rgb;
vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12;
vec3 color = mix(refracted,reflected,fresnel);
float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
color += SEA_WATER_COLOR * (p.z - SEA_HEIGHT) * 0.18 * atten;
color += vec3(specular(n,l,eye,60.0));
return color;
}
// mat3 cotangentFrame(vec3 nor, vec3 pos, vec2 uv) {
// // Get edge vectors of the pixel triangle
// vec3 dp1 = dFdx(pos);
// vec3 dp2 = dFdy(pos);
// vec2 duv1 = dFdx(uv);
// vec2 duv2 = dFdy(uv);
// // Solve the linear system
// vec3 dp2perp = cross(dp2, nor);
// vec3 dp1perp = cross(nor, dp1);
// vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
// vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
// // Construct a scale-invariant frame
// float invmax = inversesqrt(max(dot(T,T), dot(B,B)));
// return mat3(T * invmax, B * invmax, nor);
// }
vec3 getPos(float depth) {
vec3 vray = normalize(viewRay);
const float znear = 0.1;
const float zfar = 1000.0;
const float projectionA = zfar / (zfar - znear);
const float projectionB = (-zfar * znear) / (zfar - znear);
float linearDepth = projectionB / (depth * 0.5 + 0.5 - projectionA);
float viewZDist = dot(eyeLook, vray);
vec3 wposition = eye + vray * (linearDepth / viewZDist);
return wposition;
}
vec2 octahedronWrap(vec2 v) {
return (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
}
// vec3 getNormal(vec2 tc) {
// vec2 enc = texture(gbuffer0, tc).rg;
// vec3 n;
// n.z = 1.0 - abs(enc.x) - abs(enc.y);
// n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
// n = normalize(n);
// return n;
// }
vec3 caustic(vec2 uv) {
vec2 p = mod(uv*TwoPI, TwoPI)-250.0;
float loctime = time * .5+23.0;
vec2 i = vec2(p);
float c = 1.0;
float inten = .005;
// for (int n = 0; n < MAX_ITER; n++) {
float t = loctime * (1.0 - (3.5 / float(0+1)));
i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten)));
t = loctime * (1.0 - (3.5 / float(0+1)));
i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten)));
t = loctime * (1.0 - (3.5 / float(0+1)));
i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten)));
t = loctime * (1.0 - (3.5 / float(0+1)));
i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten)));
// }
c /= float(4);
c = 1.17-pow(c, 1.4);
vec3 color = vec3(pow(abs(c), 8.0));
color = clamp(color + vec3(0.0, 0.35, 0.5), 0.0, 1.0);
color = mix(color, vec3(1.0,1.0,1.0),0.3);
return color;
}
float causticX(float x, float power, float gtime)
{
float p = mod(x*TwoPI, TwoPI)-250.0;
float time = gtime * .5+23.0;
float i = p;
float c = 1.0;
float inten = .005;
// for (int n = 0; n < MAX_ITER/2; n++) {
float t = time * (1.0 - (3.5 / float(0+1)));
i = p + cos(t - i) + sin(t + i);
c += 1.0/length(p / (sin(i+t)/inten));
t = time * (1.0 - (3.5 / float(1+1)));
i = p + cos(t - i) + sin(t + i);
c += 1.0/length(p / (sin(i+t)/inten));
// }
c /= float(4);
c = 1.17-pow(c, power);
return c;
}
float godRays(vec2 uv) {
float light = 0.0;
light += pow(causticX((uv.x+0.08*uv.y)/1.7+0.5, 1.8, time*0.65),10.0)*0.05;
light -= pow((1.0-uv.y)*0.3,2.0)*0.2;
light += pow(causticX(sin(uv.x), 0.3,time*0.7),9.0)*0.4;
light += pow(causticX(cos(uv.x*2.3), 0.3,time*1.3),4.0)*0.1;
light -= pow((1.0-uv.y)*0.3,3.0);
light = clamp(light,0.0,1.0);
return light;
}
void main() {
vec4 g0 = texture(gbuffer0, texCoord); // Normal.xy, mask, depth
float gdepth = 1.0 - g0.a;
vec4 colorOriginal = texture(tex, texCoord);
if (gdepth == 0.0) {
gl_FragColor = colorOriginal;
return;
}
vec3 color = colorOriginal.rgb;
vec3 position = getPos(gdepth);
// Underwater
if (waterLevel >= eye.z) {
float t = length(eye - position);
// color *= caustic(vec2(mix(position.x,position.y,0.2),mix(position.z,position.y,0.2))*1.1);
color = mix(colorOriginal.rgb, vec3(0.0, 0.05, 0.2), 1.0 - exp(-0.3 * pow(t,1.0) ));
const float skyColor = 0.8;
color += godRays(texCoord)*mix(skyColor,1.0,texCoord.y*texCoord.y)*vec3(0.7,1.0,1.0);
gl_FragColor = vec4(color, 1.0);
return;
}
if (position.z <= waterLevel + maxAmplitude) {
// vec3 ld = normalize(vec3(0.0,0.8,1.0));
vec3 ld = normalize(vec3(0.3,-0.3,1.0));
vec3 lightDir = light - position.xyz;
vec3 eyeDir = eye - position.xyz;
vec3 l = normalize(lightDir);
vec3 v = normalize(eyeDir);
vec3 surfacePoint = heightMapTracing(eye, -v);
float depth = length(position - surfacePoint);
float depthZ = surfacePoint.z - position.z;
// float dist = length(surfacePoint - eye);
// float epsx = clamp(dot(dist/2.0,dist/2.0) * 0.001, 0.01, 0.1);
float dist = max(0.1, length(surfacePoint - eye) * 1.2);
// float epsx = dot(dist,dist) * 0.001;
float epsx = dot(dist,dist) * 0.0008;
vec3 normal = getNormal(surfacePoint, epsx);
// vec3 normal = getNormal(surfacePoint, 0.1);
float fresnel = 1.0 - max(dot(normal,-v),0.0);
fresnel = pow(fresnel,3.0) * 0.65;
// vec2 texco = texCoord.xy;
// texco.x += sin((time * timeScale) * 0.002 + 3.0 * abs(position.z)) * (refractionScale * min(depthZ, 1.0));
// vec3 refraction = texture(tex, texco).rgb;
// vec3 _p = getPos(1.0 - texture(gbuffer0, texco).a);
// if (_p.z > waterLevel) {
// refraction = colorOriginal.rgb;
// }
// vec3 reflect = textureLod(senvmapRadiance, envMapEquirect(reflect(v,normal)), 2.0).rgb;
// vec3 depthN = vec3(depth * fadeSpeed);
// vec3 waterCol = vec3(clamp(length(sunColor) / sunScale, 0.0, 1.0));
// refraction = mix(mix(refraction, depthColour * waterCol, clamp(depthN / visibility, 0.0, 1.0)), bigDepthColour * waterCol, clamp(depthZ / extinction, 0.0, 1.0));
// float foam = 0.0;
// // texco = (surfacePoint.xy + v.xy * 0.1) * 0.05 + (time * timeScale) * 0.00001 * wind + sin((time * timeScale) * 0.001 + position.x) * 0.005;
// // vec2 texco2 = (surfacePoint.xy + v.xy * 0.1) * 0.05 + (time * timeScale) * 0.00002 * wind + sin((time * timeScale) * 0.001 + position.y) * 0.005;
// // if (depthZ < foamExistence.x) {
// // foam = (texture(fmap, texco).r + texture(fmap, texco2).r) * 0.5;
// // }
// // else if (depthZ < foamExistence.y) {
// // foam = mix((texture(fmap, texco).r + texture(fmap, texco2).r) * 0.5, 0.0,
// // (depthZ - foamExistence.x) / (foamExistence.y - foamExistence.x));
// // }
// // if (maxAmplitude - foamExistence.z > 0.0001) {
// // foam += (texture(fmap, texco).r + texture(fmap, texco2).r) * 0.5 *
// // clamp((waterLevel - (waterLevel + foamExistence.z)) / (maxAmplitude - foamExistence.z), 0.0, 1.0);
// // }
// vec3 mirrorEye = (2.0 * dot(v, normal) * normal - v);
// float dotSpec = clamp(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5, 0.0, 1.0);
// vec3 specular = (1.0 - fresnel) * clamp(-lightDir.z, 0.0, 1.0) * ((pow(dotSpec, 512.0)) * (shininess * 1.8 + 0.2))* sunColor;
// specular += specular * 25 * clamp(shininess - 0.05, 0.0, 1.0) * sunColor;
// color = mix(refraction, reflect, fresnel);
// color = clamp(color + max(specular, foam * sunColor), 0.0, 1.0);
// color = mix(refraction, color, clamp(depth * shoreHardness, 0.0, 1.0));
color = getSeaColor(surfacePoint,normal,ld,-v,surfacePoint-eye);
// color = pow(color, vec3(2.2));
color = mix(colorOriginal.rgb, color, clamp(depthZ * 1.8, 0.0, 1.0));
}
// if (position.z > waterLevel) {
// color = colorOriginal.rgb;
// }
gl_FragColor.rgb = color;
}

View file

@ -0,0 +1,50 @@
{
"contexts": [
{
"id": "water_pass",
"params": [
{
"id": "depth_write",
"value": "true"
},
{
"id": "compare_mode",
"value": "always"
},
{
"id": "cull_mode",
"value": "none"
}
],
"links": [
{
"id": "eye",
"link": "_cameraPosition"
},
{
"id": "eyeLook",
"link": "_cameraLook"
},
{
"id": "light",
"link": "_lightPosition"
},
{
"id": "invVP",
"link": "_inverseViewProjectionMatrix"
},
{
"id": "time",
"link": "_time"
},
{
"id": "senvmapRadiance",
"link": "_envmapRadiance"
}
],
"texture_params": [],
"vertex_shader": "water_pass.vert.glsl",
"fragment_shader": "water_pass.frag.glsl"
}
]
}

View file

@ -0,0 +1,28 @@
#version 450
#ifdef GL_ES
precision highp float;
#endif
uniform mat4 invVP;
uniform vec3 eye;
in vec2 pos;
out vec2 texCoord;
out vec3 viewRay;
const vec2 madd = vec2(0.5, 0.5);
void main() {
// Scale vertex attribute to [0-1] range
texCoord = pos.xy * madd + madd;
gl_Position = vec4(pos.xy, 0.0, 1.0);
// NDC (at the back of cube)
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
v = vec4(invVP * v);
v.xyz /= v.w;
viewRay = v.xyz - eye;
}

View file

@ -0,0 +1,35 @@
// Based on work by David Li(http://david.li/waves)
#version 450
#ifdef GL_ES
precision mediump float;
#endif
const float PI = 3.14159265359;
const float G = 9.81;
const float KM = 370.0;
in vec2 texCoord;
uniform sampler2D u_phases;
uniform float u_deltaTime;
const float resolution = 512.0;
const float size = 250.0;
float omega(float k) {
return sqrt(G * k * (1.0 + k * k / KM * KM));
}
void main() {
vec2 coordinates = texCoord * resolution;// gl_FragCoord.xy - 0.5;
float n = (coordinates.x < resolution * 0.5) ? coordinates.x : coordinates.x - resolution;
float m = (coordinates.y < resolution * 0.5) ? coordinates.y : coordinates.y - resolution;
vec2 waveVector = (2.0 * PI * vec2(n, m)) / size;
float phase = texture(u_phases, texCoord).r;
float deltaPhase = omega(length(waveVector)) * u_deltaTime;
phase = mod(phase + deltaPhase, 2.0 * PI);
gl_FragColor = vec4(phase, 0.0, 0.0, 0.0);
}

View file

@ -0,0 +1,18 @@
#version 450
#ifdef GL_ES
precision highp float;
#endif
in vec2 pos;
out vec2 texCoord;
const vec2 madd = vec2(0.5, 0.5);
void main() {
// Scale vertex attribute to [0-1] range
texCoord = pos.xy * madd + madd;
gl_Position = vec4(pos.xy, 0.0, 1.0);
}

View file

@ -0,0 +1,59 @@
// Based on work by David Li(http://david.li/waves)
#version 450
#ifdef GL_ES
precision mediump float;
#endif
const float PI = 3.14159265359;
const float G = 9.81;
const float KM = 370.0;
const float size = 250.0;
const float resolution = 512.0;
const float choppiness = 1.5;
uniform sampler2D texPhases;
uniform sampler2D texInitialSpectrum;
in vec2 texCoord;
vec2 multiplyComplex(vec2 a, vec2 b) {
return vec2(a[0] * b[0] - a[1] * b[1], a[1] * b[0] + a[0] * b[1]);
}
vec2 multiplyByI(vec2 z) {
return vec2(-z[1], z[0]);
}
float omega(float k) {
return sqrt(G * k * (1.0 + k * k / KM * KM));
}
void main() {
vec2 coordinates = texCoord * resolution;// gl_FragCoord.xy - 0.5;
float n = (coordinates.x < resolution * 0.5) ? coordinates.x : coordinates.x - resolution;
float m = (coordinates.y < resolution * 0.5) ? coordinates.y : coordinates.y - resolution;
vec2 waveVector = (2.0 * PI * vec2(n, m)) / size;
float phase = texture2D(texPhases, texCoord).r;
vec2 phaseVector = vec2(cos(phase), sin(phase));
vec2 h0 = texture2D(texInitialSpectrum, texCoord).rg;
vec2 h0Star = texture2D(texInitialSpectrum, vec2(1.0 - texCoord + 1.0 / resolution)).rg;
h0Star.y *= -1.0;
vec2 h = multiplyComplex(h0, phaseVector) + multiplyComplex(h0Star, vec2(phaseVector.x, -phaseVector.y));
vec2 hX = -multiplyByI(h * (waveVector.x / length(waveVector))) * choppiness;
vec2 hZ = -multiplyByI(h * (waveVector.y / length(waveVector))) * choppiness;
// No DC term
if (waveVector.x == 0.0 && waveVector.y == 0.0) {
h = vec2(0.0);
hX = vec2(0.0);
hZ = vec2(0.0);
}
gl_FragColor = vec4(hX + multiplyByI(h), hZ);
}

View file

@ -0,0 +1,18 @@
#version 450
#ifdef GL_ES
precision highp float;
#endif
in vec2 pos;
out vec2 texCoord;
const vec2 madd = vec2(0.5, 0.5);
void main() {
// Scale vertex attribute to [0-1] range
texCoord = pos.xy * madd + madd;
gl_Position = vec4(pos.xy, 0.0, 1.0);
}

View file

@ -0,0 +1,48 @@
// Based on work by David Li(http://david.li/waves)
// GPU FFT using a Stockham formulation
#version 450
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D texInput;
in vec2 texCoord;
const float PI = 3.14159265359;
const float transformSize = 512.0;
const float texSize = 512.0;
const float subtransformSize = 250.0;
vec2 multiplyComplex(vec2 a, vec2 b) {
return vec2(a[0] * b[0] - a[1] * b[1], a[1] * b[0] + a[0] * b[1]);
}
void main() {
// #ifdef HORIZONTAL
// float index = texCoord.x * transformSize - 0.5;
// #else
float index = texCoord.y * transformSize - 0.5;
// #endif
float evenIndex = floor(index / subtransformSize) * (subtransformSize * 0.5) + mod(index, subtransformSize * 0.5);
//transform two complex sequences simultaneously
// #ifdef HORIZONTAL
// vec4 even = texture(texInput, vec2(evenIndex + 0.5, texCoord.y * texSize) / transformSize);
// vec4 odd = texture(texInput, vec2(evenIndex + transformSize * 0.5 + 0.5, texCoord.y * texSize) / transformSize);
// #else
// gl_FragCoord.x / texCoord.x * texSize
vec4 even = texture(texInput, vec2(texCoord.x * texSize, evenIndex + 0.5) / transformSize);
vec4 odd = texture(texInput, vec2(texCoord.x * texSize, evenIndex + transformSize * 0.5 + 0.5) / transformSize);
// #endif
float twiddleArgument = -2.0 * PI * (index / subtransformSize);
vec2 twiddle = vec2(cos(twiddleArgument), sin(twiddleArgument));
vec2 outputA = even.xy + multiplyComplex(twiddle, odd.xy);
vec2 outputB = even.zw + multiplyComplex(twiddle, odd.zw);
gl_FragColor = vec4(outputA, outputB);
}

View file

@ -0,0 +1,18 @@
#version 450
#ifdef GL_ES
precision highp float;
#endif
in vec2 pos;
out vec2 texCoord;
const vec2 madd = vec2(0.5, 0.5);
void main() {
// Scale vertex attribute to [0-1] range
texCoord = pos.xy * madd + madd;
gl_Position = vec4(pos.xy, 0.0, 1.0);
}