1
0
Fork 0

Merge branch 'master' of gitorious.org:fg/fgdata

This commit is contained in:
Durk Talsma 2011-10-07 17:48:10 +02:00
commit 61c5c35ff4
16 changed files with 442 additions and 128 deletions

View file

@ -43,8 +43,6 @@ The cloud is defined by the following properties:
<height-map-texture> - whether to choose the vertical texture index based on
sprite height within the clouds (default false)
<num-sprites> - Number of sprite to generate for the cloud (default 20)
<bottom-shade> - Light multiplier for sprites at the bottom of the cloud
(default 1.0)
<min-sprite-width-m> - minimum width of the sprites used to create the cloud
(default 200)
<max-sprite-width-m> - maximum width of the sprites used to create the cloud
@ -56,7 +54,39 @@ The cloud is defined by the following properties:
<z-scale> - vertical scaling factor to apply to to the sprite after
billboarding. A small value would create a sprite that
looks squashed when viewed from the side. (default 1.0)
<min-bottom-lighting-factor> - See Shading below (default 1.0)
<max-bottom-lighting-factor> - See Shading below (default min-...-factor + 0.1)
<min-middle-lighting-factor> - See Shading below (default 1.0)
<max-middle-lighting-factor> - See Shading below (default min-...-factor + 0.1)
<min-top-lighting-factor> - See Shading below (default 1.0)
<max-top-lighting-factor> - See Shading below (default min-...-factor + 0.1)
<min-shade-lighting-factor> - See Shading below (default 0.5)
<max-shade-lighting-factor> - See Shading below (default min-...-factor + 0.1)
Shading
-------
the [min|max]-...-lighting-factor properties allow you to define diffuse lighting
multipliers to the bottom, middle, top, sunny and shaded parts of the cloud. In
each case, individual clouds will have a random multiplier between the min and
max values used to allow for some variation between individual clouds.
The top, middle and bottom lighting factors are applied based on the pixels vertical
positon in the cloud. A linear interpolation is used either between top/middle (if
the pixel is above the middle of the cloud) or middle/bottom (if the pixel is below
the middle of the cloud).
The top factor is also applied to _all_ pixels on the sunny side of the cloud. The
shade factor is applied based on the pixel position away from the sun, linearly
interpolated from top to shade. E.g this is not a straight linear interpolation
from top to shade across the entire cloud.
The final lighting factor is determined by the minimum of the vertical factor and
the sunny/shade factor. Note that this is applied to the individual pixels, not
sprites.
Textures
--------
The texture to use for the sprites is defined in the <texture> tag.
To allow some variation, you can create a texture file containing multiple

View file

@ -60,6 +60,10 @@
<name>usrAttr2</name>
<index>11</index>
</attribute>
<attribute>
<name>usrAttr3</name>
<index>12</index>
</attribute>
</program>
<uniform>
<name>baseTexture</name>

View file

@ -12,7 +12,9 @@
</texture>
<texture n="2">
<!--<image>Textures/Water/water-normalmap.png</image>-->
<image>Textures/Water/normalmap2.png</image>
<!--<image>Textures/Water/water-normalmap2.dds</image>-->
<image>Textures/Water/waves-ver10-nm.dds</image>
<!--<image>Textures/Water/caustic-nm.png</image>-->
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
@ -20,7 +22,9 @@
</texture>
<texture n="3">
<!--<image>Textures/Water/water-dudv.png</image>-->
<image>Textures/Water/dudvmap2.png</image>
<!--<image>Textures/Water/dudvmap2.png</image>-->
<image>Textures/Water/waves-ver10-dudv.dds</image>
<!--<image>Textures/Water/water-reflection-grey.png</image>-->
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
@ -34,7 +38,14 @@
<internal-format>normalized</internal-format>
</texture>
<texture n="5">
<image>Textures/Water/sea_foam.png</image>
<image>Textures/Water/sea_foam.dds</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<texture n="6">
<image>Textures/Water/perlin-noise-nm.dds</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
@ -73,6 +84,10 @@
<windN>
<use>/environment/config/boundary/entry[0]/wind-from-north-fps</use>
</windN>
<wind-from>
<use>/environment/config/boundary/entry[0]/wind-from-heading-deg</use>
</wind-from>
</parameters>
<technique n="8">
@ -218,6 +233,28 @@
<use>texture[5]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit>
<unit>6</unit>
<image>
<use>texture[6]/image</use>
</image>
<filter>
<use>texture[6]/filter</use>
</filter>
<wrap-s>
<use>texture[6]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[6]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[6]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit>
<unit>9</unit>
<type>noise</type>
</texture-unit>
<program>
<vertex-shader>Shaders/water.vert</vertex-shader>
<fragment-shader>Shaders/water.frag</fragment-shader>
@ -247,6 +284,11 @@
<type>sampler-2d</type>
<value type="int">5</value>
</uniform>
<uniform>
<name>perlin_normalmap</name>
<type>sampler-2d</type>
<value type="int">6</value>
</uniform>
<uniform>
<name>saturation</name>
<type>float</type>
@ -317,6 +359,18 @@
<use>windN</use>
</value>
</uniform>
<uniform>
<name>WindFrom</name>
<type>float</type>
<value>
<use>wind-from</use>
</value>
</uniform>
<uniform>
<name>Noise</name>
<type>sampler-3d</type>
<value type="int">9</value>
</uniform>
</pass>
</technique>
<technique n="9">

View file

@ -35,33 +35,29 @@ ns = Nimbostratus (Rain cloud)
<clouds>
<cb-large>
<min-cloud-width-m>1600</min-cloud-width-m>
<max-cloud-width-m>2000</max-cloud-width-m>
<min-cloud-height-m>4000</min-cloud-height-m>
<max-cloud-height-m>3000</max-cloud-height-m>
<num-sprites>10</num-sprites>
<texture>cl_cumulus.png</texture>
<num-textures-x>4</num-textures-x>
<num-textures-y>4</num-textures-y>
<bottom-shade>0.3</bottom-shade>
<min-bottom-lighting-factor>0.3</min-bottom-lighting-factor>
<min-shade-lighting-factor>0.4</min-shade-lighting-factor>
<min-sprite-width-m>800</min-sprite-width-m>
<max-sprite-width-m>1200</max-sprite-width-m>
<min-sprite-height-m>800</min-sprite-height-m>
<max-sprite-height-m>1200</max-sprite-height-m>
<height-map-texture>true</height-map-texture>
</cb-large>
<cb-small>
<min-cloud-width-m>800</min-cloud-width-m>
<max-cloud-width-m>400</max-cloud-width-m>
<min-cloud-height-m>500</min-cloud-height-m>
<max-cloud-height-m>200</max-cloud-height-m>
<min-cloud-height-m>800</min-cloud-height-m>
<num-sprites>10</num-sprites>
<texture>cl_cumulus.png</texture>
<num-textures-x>4</num-textures-x>
<num-textures-y>4</num-textures-y>
<bottom-shade>0.3</bottom-shade>
<min-bottom-lighting-factor>0.3</min-bottom-lighting-factor>
<min-shade-lighting-factor>0.4</min-shade-lighting-factor>
<min-sprite-width-m>400</min-sprite-width-m>
<max-sprite-width-m>800</max-sprite-width-m>
<min-sprite-height-m>400</min-sprite-height-m>
<max-sprite-height-m>800</max-sprite-height-m>
<height-map-texture>true</height-map-texture>
</cb-small>
<cu-large>
<min-cloud-width-m>600</min-cloud-width-m>
@ -69,89 +65,95 @@ ns = Nimbostratus (Rain cloud)
<min-cloud-height-m>400</min-cloud-height-m>
<max-cloud-height-m>800</max-cloud-height-m>
<num-sprites>20</num-sprites>
<texture>cl_cumulus.png</texture>
<texture>cl_cumulus2.png</texture>
<num-textures-x>4</num-textures-x>
<num-textures-y>4</num-textures-y>
<bottom-shade>0.6</bottom-shade>
<min-bottom-lighting-factor>0.2</min-bottom-lighting-factor>
<min-shade-lighting-factor>0.3</min-shade-lighting-factor>
<min-sprite-width-m>400</min-sprite-width-m>
<max-sprite-width-m>700</max-sprite-width-m>
<min-sprite-height-m>300</min-sprite-height-m>
<max-sprite-height-m>700</max-sprite-height-m>
<height-map-texture>true</height-map-texture>
</cu-large>
<cu-small>
<min-cloud-width-m>300</min-cloud-width-m>
<max-cloud-width-m>800</max-cloud-width-m>
<min-cloud-height-m>200</min-cloud-height-m>
<max-cloud-height-m>300</max-cloud-height-m>
<num-sprites>10</num-sprites>
<texture>cl_cumulus.png</texture>
<min-cloud-width-m>600</min-cloud-width-m>
<max-cloud-width-m>900</max-cloud-width-m>
<min-cloud-height-m>400</min-cloud-height-m>
<max-cloud-height-m>600</max-cloud-height-m>
<num-sprites>20</num-sprites>
<texture>cl_cumulus2.png</texture>
<num-textures-x>4</num-textures-x>
<num-textures-y>4</num-textures-y>
<bottom-shade>0.7</bottom-shade>
<min-sprite-width-m>200</min-sprite-width-m>
<min-bottom-lighting-factor>0.4</min-bottom-lighting-factor>
<min-shade-lighting-factor>0.5</min-shade-lighting-factor>
<min-sprite-width-m>300</min-sprite-width-m>
<max-sprite-width-m>400</max-sprite-width-m>
<min-sprite-height-m>150</min-sprite-height-m>
<min-sprite-height-m>200</min-sprite-height-m>
<max-sprite-height-m>300</max-sprite-height-m>
<height-map-texture>true</height-map-texture>
</cu-small>
<ns-large>
<min-cloud-width-m>1200</min-cloud-width-m>
<max-cloud-width-m>3000</max-cloud-width-m>
<min-cloud-height-m>200</min-cloud-height-m>
<max-cloud-height-m>400</max-cloud-height-m>
<min-cloud-height-m>400</min-cloud-height-m>
<max-cloud-height-m>800</max-cloud-height-m>
<num-sprites>40</num-sprites>
<texture>cl_st.png</texture>
<num-textures-x>1</num-textures-x>
<num-textures-y>1</num-textures-y>
<bottom-shade>0.2</bottom-shade>
<min-bottom-lighting-factor>0.2</min-bottom-lighting-factor>
<min-sprite-width-m>300</min-sprite-width-m>
<max-sprite-width-m>600</max-sprite-width-m>
<min-sprite-height-m>100</min-sprite-height-m>
<max-sprite-height-m>200</max-sprite-height-m>
<height-map-texture>false</height-map-texture>
<z-scale>0.5</z-scale>
</ns-large>
<ns-white>
<min-cloud-width-m>600</min-cloud-width-m>
<max-cloud-width-m>2000</max-cloud-width-m>
<min-cloud-height-m>200</min-cloud-height-m>
<max-cloud-height-m>300</max-cloud-height-m>
<min-cloud-height-m>400</min-cloud-height-m>
<max-cloud-height-m>600</max-cloud-height-m>
<num-sprites>40</num-sprites>
<texture>cl_st.png</texture>
<num-textures-x>1</num-textures-x>
<num-textures-y>1</num-textures-y>
<bottom-shade>0.3</bottom-shade>
<min-bottom-lighting-factor>0.3</min-bottom-lighting-factor>
<min-sprite-width-m>300</min-sprite-width-m>
<max-sprite-width-m>600</max-sprite-width-m>
<min-sprite-height-m>100</min-sprite-height-m>
<max-sprite-height-m>200</max-sprite-height-m>
<height-map-texture>false</height-map-texture>
<z-scale>0.5</z-scale>
</ns-white>
<st-small>
<min-cloud-width-m>800</min-cloud-width-m>
<max-cloud-width-m>1500</max-cloud-width-m>
<min-cloud-height-m>100</min-cloud-height-m>
<max-cloud-height-m>200</max-cloud-height-m>
<num-sprites>40</num-sprites>
<texture>cl_st.png</texture>
<num-textures-x>1</num-textures-x>
<num-textures-y>1</num-textures-y>
<bottom-shade>0.9</bottom-shade>
<min-sprite-width-m>300</min-sprite-width-m>
<max-sprite-width-m>600</max-sprite-width-m>
<min-sprite-height-m>200</min-sprite-height-m>
<max-sprite-height-m>400</max-sprite-height-m>
</st-small>
<st-large>
<min-cloud-width-m>1800</min-cloud-width-m>
<max-cloud-width-m>2500</max-cloud-width-m>
<min-cloud-width-m>1000</min-cloud-width-m>
<min-cloud-height-m>200</min-cloud-height-m>
<max-cloud-height-m>400</max-cloud-height-m>
<num-sprites>40</num-sprites>
<texture>cl_st.png</texture>
<num-textures-x>1</num-textures-x>
<num-textures-y>1</num-textures-y>
<bottom-shade>0.9</bottom-shade>
<texture>cl_cumulus.png</texture>
<num-textures-x>4</num-textures-x>
<num-textures-y>4</num-textures-y>
<min-bottom-lighting-factor>0.9</min-bottom-lighting-factor>
<min-sprite-width-m>400</min-sprite-width-m>
<max-sprite-width-m>800</max-sprite-width-m>
<min-sprite-height-m>300</min-sprite-height-m>
<max-sprite-height-m>500</max-sprite-height-m>
<min-sprite-height-m>400</min-sprite-height-m>
<max-sprite-height-m>800</max-sprite-height-m>
<height-map-texture>false</height-map-texture>
<z-scale>0.3</z-scale>
</st-small>
<st-large>
<min-cloud-width-m>2000</min-cloud-width-m>
<min-cloud-height-m>1000</min-cloud-height-m>
<num-sprites>40</num-sprites>
<texture>cl_st.png</texture>
<num-textures-x>1</num-textures-x>
<num-textures-y>1</num-textures-y>
<min-bottom-lighting-factor>0.9</min-bottom-lighting-factor>
<min-sprite-width-m>600</min-sprite-width-m>
<min-sprite-height-m>600</min-sprite-height-m>
<height-map-texture>false</height-map-texture>
<z-scale>0.4</z-scale>
</st-large>
</clouds>
<boxes>

View file

@ -7,6 +7,65 @@
##
###############################################################################
###############################################################################
# Event broadcast channel using a MP enabled string property.
# Events from users in multiplayer.ignore are ignored.
#
# EventChannel.new(mpp_path)
# Create a new event broadcast channel. Any MP user with the same
# primitive will receive all messages sent to the channel from the point
# she/he joined (barring severe MP packet loss).
# NOTE: Message delivery is not guaranteed.
# mpp_path - MP property path : string
#
# EventChannel.register(event_hash, handler)
# Register a handler for the event identified by the hash event_hash.
# event_hash - hash value for the event : a unique 4 character string
# handler - a handler function for the event : func (msg)
#
# EventChannel.deregister(event_hash)
# Deregister the handler for the event identified by the hash event_hash.
# event_hash - hash value for the event : a unique 4 character string
#
# EventChannel.send(event_hash, msg)
# Sends the event event_hash with the message msg to the channel.
# event_hash - hash value for the event : a unique 4 character string
# msg - text string with Binary data encoded data : string
#
# EventChannel.die()
# Destroy this EventChannel instance.
#
var EventChannel = {};
EventChannel.new = func (mpp_path) {
var obj = BroadcastChannel.new(mpp_path,
func (n, msg) { obj._process(n, msg) });
# Save send from being overriden.
obj.parent_send = obj.send;
# Put EventChannel methods before BroadcastChannel methods.
obj.parents = [EventChannel] ~ obj.parents;
obj.events = {};
return obj;
}
EventChannel.register = func (event_hash,
handler) {
me.events[event_hash] = handler;
}
EventChannel.deregister = func (event_hash) {
delete(me.events, event_hash);
}
EventChannel.send = func (event_hash,
msg) {
me.parent_send(event_hash ~ msg);
}
############################################################
# Internals.
EventChannel._process = func (n, msg) {
var event_hash = Binary.readHash(msg);
if (contains(me.events, event_hash)) {
me.events[event_hash](substr(msg, Binary.sizeOf["Hash"]));
}
}
###############################################################################
# Broadcast primitive using a MP enabled string property.
# Broadcasts from users in multiplayer.ignore are ignored.
@ -60,6 +119,7 @@ BroadcastChannel.new = func (mpp_path, process,
send_buf : [],
peers : {},
loopid : 0,
running : 0,
PERIOD : 1.3,
last_time : 0.0, # For join handling.
last_send : 0.0, # For the send queue
@ -74,7 +134,8 @@ BroadcastChannel.new = func (mpp_path, process,
return obj;
}
BroadcastChannel.send = func (msg) {
if (me.send_node == nil) return;
if (!me.running or me.send_node == nil)
return;
var t = getprop("/sim/time/elapsed-sec");
if (((t - me.last_send) > me.SEND_TIME) and (size(me.send_buf) == 0)) {
@ -87,13 +148,21 @@ BroadcastChannel.send = func (msg) {
}
BroadcastChannel.die = func {
me.loopid += 1;
me.running = 0;
# print("BroadcastChannel[" ~ me.mpp_path ~ "] ... destroyed.");
}
BroadcastChannel.start = func {
me.loopid += 1;
settimer(func { me._loop_(me.loopid); }, 0, 1);
if (!getprop("/sim/multiplay/online")) {
me.stop();
} else {
#print("mp_broadcast.nas: starting channel " ~ me.send_node.getPath() ~ ".");
me.running = 1;
me._loop_(me.loopid += 1);
}
}
BroadcastChannel.stop = func {
#print("mp_broadcast.nas: stopping channel " ~ me.send_node.getPath() ~ ".");
me.running = 0;
me.loopid += 1;
}
@ -147,8 +216,11 @@ BroadcastChannel.update = func {
}
}
}
BroadcastChannel._loop_ = func(id) {
BroadcastChannel._loop_ = func (id) {
me.running or return;
id == me.loopid or return;
#print("mp_broadcast.nas: " ~ me.send_node.getPath() ~ ":" ~ id ~ ".");
me.update();
settimer(func { me._loop_(id); }, 0, 1);
}
@ -159,6 +231,7 @@ BroadcastChannel._loop_ = func(id) {
# NOTE: MP is picky about what it sends in a string propery.
# Encode 7 bits as a printable 8 bit character.
var Binary = {};
Binary.TWOTO28 = 268435456;
Binary.TWOTO31 = 2147483648;
Binary.TWOTO32 = 4294967296;
Binary.sizeOf = {};
@ -230,6 +303,21 @@ Binary.decodeCoord = func (str) {
Binary.decodeDouble(substr(str, 20)));
return coord;
}
############################################################
# Encodes a string as a hash value.
Binary.sizeOf["Hash"] = 4;
Binary.stringHash = func (str) {
var hash = 0;
for(var i=0; i<size(str); i+=1) {
hash += math.mod(32*hash + str[i], Binary.TWOTO28-3);
}
return substr(Binary.encodeInt(hash), 1, 4);
}
############################################################
# Decodes an encoded geo.Coord object.
Binary.readHash = func (str) {
return substr(str, 0, Binary.sizeOf["Hash"]);
}
######################################################################
###############################################################################

62
Nasal/scenery.nas Normal file
View file

@ -0,0 +1,62 @@
###############################################################################
##
## Support tools for multiplayer enabled scenery objects.
##
## Copyright (C) 2011 Anders Gidenstam (anders(at)gidenstam.org)
## This file is licensed under the GPL license version 2 or later.
##
###############################################################################
# The event channel for scenery objects.
# See mp_broadcast.EventChannel for documentation.
var events = nil;
###############################################################################
# An extended aircraft.door that transmits the door events over MP using the
# scenery.events channel.
# Use only for single instance objects (e.g. static scenery objects).
#
# Note: Currently toggle() is the only shared event.
var sharedDoor = {
new: func(node, swingtime, pos = 0) {
var obj = aircraft.door.new(node, swingtime, pos);
obj.parents = [sharedDoor] ~ obj.parents;
obj.event_hash = mp_broadcast.Binary.stringHash
(isa(node, props.Node) ? node.getPath() : node);
events.register(obj.event_hash, func (msg) { obj._process(msg) });
return obj;
},
toggle: func {
events.send(me.event_hash, mp_broadcast.Binary.encodeByte(me.target));
me.move(me.target);
},
destroy : func {
events.deregister(me.event_hash);
},
_process : func (msg) {
me.target = mp_broadcast.Binary.decodeByte(msg);
me.move(me.target);
}
};
###############################################################################
# Internals
var shared_pp = "scenery/share-events";
_setlistener("sim/signals/nasal-dir-initialized", func {
events = mp_broadcast.EventChannel.new("scenery/events");
if (!getprop("/sim/multiplay/online") or !getprop(shared_pp)) {
#print("scenery.nas: stopping event sharing.");
events.stop();
}
setlistener(shared_pp, func (n) {
if (getprop("/sim/signals/reinit")) return; # Ignore resets.
if (n.getValue() and getprop("/sim/multiplay/online")) {
#print("scenery.nas: starting event sharing.");
events.start();
} else {
#print("scenery.nas: stopping event sharing.");
events.stop();
}
});
});

View file

@ -7,13 +7,17 @@ uniform float range; // From /sim/rendering/clouds3d-vis-range
attribute vec3 usrAttr1;
attribute vec3 usrAttr2;
attribute vec3 usrAttr3;
float textureIndexX = usrAttr1.r;
float textureIndexY = usrAttr1.g;
float wScale = usrAttr1.b;
float hScale = usrAttr2.r;
float shade = usrAttr2.g;
float shade_factor = usrAttr2.g;
float cloud_height = usrAttr2.b;
float bottom_factor = usrAttr3.r;
float middle_factor = usrAttr3.g;
float top_factor = usrAttr3.b;
void main(void)
{
@ -34,35 +38,44 @@ void main(void)
gl_Position.xyz = gl_Vertex.x * u;
gl_Position.xyz += gl_Vertex.y * r * wScale;
gl_Position.xyz += gl_Vertex.z * w * hScale;
gl_Position.xyz += gl_Color.xyz;
// Apply Z scaling to allow sprites to be squashed in the z-axis
gl_Position.z = gl_Position.z * gl_Color.w;
// Now shift the sprite to the correct position in the cloud.
gl_Position.xyz += gl_Color.xyz;
// Determine a lighting normal based on the vertex position from the
// center of the cloud, so that sprite on the opposite side of the cloud to the sun are darker.
float n = dot(normalize(-gl_LightSource[0].position.xyz),
normalize(vec3(gl_ModelViewMatrix * vec4(- gl_Position.x, - gl_Position.y, - gl_Position.z,0.0))));
normalize(vec3(gl_ModelViewMatrix * vec4(- gl_Position.x, - gl_Position.y, - gl_Position.z, 0.0))));
// Determine the position - used for fog and shading calculations
vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Position);
float fogCoord = abs(ecPosition.z);
// Determine fractional height of vertex from 0 at the bottom, and 1 at mid-height.
// Used to determine shading.
float fract = smoothstep(0.0, cloud_height, gl_Position.z + cloud_height);
// Determine the shading of the vertex. We shade it based on it's position
// in the cloud relative to the sun, and it's vertical position in the cloud.
float shade = mix(shade_factor, top_factor, smoothstep(-0.3, 0.0, n));
//if (n < 0) {
// shade = mix(top_factor, shade_factor, abs(n));
//}
float h = gl_Position.z;
shade = min(shade,
min(mix(bottom_factor, middle_factor, smoothstep(0.0, 0.5 * h, h)),
mix(middle_factor, top_factor, smoothstep(0.5 * h, h, h)) ) );
//float h = gl_Position.z / cloud_height;
//if (h < 0.5) {
// shade = min(shade, mix(bottom_factor, middle_factor, smoothstep(0.0, 0.5, h)));
//} else {
// shade = min(shade, mix(middle_factor, top_factor, smoothstep(2.0 * (h - 0.5)));
// }
// Final position of the sprite
gl_Position = gl_ModelViewProjectionMatrix * gl_Position;
// Determine the shading of the sprite based on its vertical position and position relative to the sun.
n = min(smoothstep(-0.5, 0.0, n), fract);
// Determine the shading based on a mixture from the backlight to the front
vec4 backlight = gl_LightSource[0].diffuse * shade;
gl_FrontColor = mix(backlight, gl_LightSource[0].diffuse, n);
gl_FrontColor += gl_FrontLightModelProduct.sceneColor;
gl_FrontColor = gl_LightSource[0].diffuse * shade + gl_FrontLightModelProduct.sceneColor;
// As we get within 100m of the sprite, it is faded out. Equally at large distances it also fades out.
gl_FrontColor.a = min(smoothstep(10.0, 100.0, fogCoord), 1.0 - smoothstep(range*0.8, range, fogCoord));

View file

@ -2,18 +2,23 @@
// http://www.bonzaisoftware.com/water_tut.html and its glsl conversion
// available at http://forum.bonzaisoftware.com/viewthread.php?tid=10
// © Michael Horsch - 2005
// Major update and revisions - 2011-10-07
// © Emilian Huminiuc and Vivian Meazza
#version 120
#pragma debug(on)
uniform sampler2D water_normalmap;
uniform sampler2D water_reflection;
uniform sampler2D water_dudvmap;
uniform sampler2D water_reflection_grey;
uniform sampler2D sea_foam;
uniform sampler2D perlin_normalmap;
uniform sampler3D Noise;
uniform float saturation, Overcast, WindE, WindN;
uniform float CloudCover0, CloudCover1, CloudCover2, CloudCover3, CloudCover4;
uniform float osg_SimulationTime;
uniform int Status;
varying vec4 waterTex1; //moving texcoords
@ -24,12 +29,23 @@ varying vec3 viewerdir;
varying vec3 lightdir;
varying vec3 normal;
/////// functions /////////
void rotationmatrix(in float angle, out mat4 rotmat)
{
rotmat = mat4( cos( angle ), -sin( angle ), 0.0, 0.0,
sin( angle ), cos( angle ), 0.0, 0.0,
0.0 , 0.0 , 1.0, 0.0,
0.0 , 0.0 , 0.0, 1.0 );
}
void main(void)
{
const vec4 sca = vec4(0.005, 0.005, 0.005, 0.005);
const vec4 sca2 = vec4(0.02, 0.02, 0.02, 0.02);
const vec4 tscale = vec4(0.25, 0.25, 0.25, 0.25);
mat4 RotationMatrix;
// compute direction to viewer
vec3 E = normalize(viewerdir);
@ -39,40 +55,55 @@ void main(void)
// half vector
vec3 H = normalize(L + E);
const float water_shininess = 240.0;
vec3 Normal = normalize(normal);
// calculate wind effects
float windEffect = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.6;
float windScale = 10.0/(6.0 + 8.0 * smoothstep(0.0,0.8,windEffect * 0.05));
const float water_shininess = 240.0;
// approximate cloud cover
float cover = 0.0;
//bool Status = true;
float windEffect = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.6; //wind speed in kt
float windScale = 15.0/(3.0 + windEffect); //wave scale
float windEffect_low = 0.4 + 0.6 * smoothstep(0.0, 5.0, windEffect); //low windspeed wave filter
float waveRoughness = 0.15 + smoothstep(0.0, 15.0, windEffect); //wave roughness filter
//float noise_factor = 0.2 + 0.15 * smoothstep(0.0, 40.0, windEffect);
if (Status == 1){
cover = min(min(min(min(CloudCover0, CloudCover1),CloudCover2),CloudCover3),CloudCover4);
} else {
// hack to allow for Overcast not to be set by Local Weather
if (Overcast == 0){
cover = 5;
} else {
cover = Overcast * 5;
}
}
vec4 viewt = normalize(waterTex4);
vec4 disdis = texture2D(water_dudvmap, vec2(waterTex2 * tscale)* windScale) * 2.0 - 1.0;
vec4 dist = texture2D(water_dudvmap, vec2(waterTex1 + disdis*sca2)* windScale) * 2.0 - 1.0;
vec4 fdist = normalize(dist);
vec4 dist = texture2D(water_dudvmap, vec2(waterTex1 + disdis*sca2)* windScale) * 2.0 - 1.0;
dist *= (0.6 + 0.5 * smoothstep(0.0, 15.0, windEffect));
vec4 fdist = normalize(dist);
fdist = -fdist; //dds fix
fdist *= sca;
//normalmap
vec4 nmap0 = texture2D(water_normalmap, vec2(waterTex1+ disdis*sca2) * windScale) * 2.0 - 1.0;
vec4 nmap2 = texture2D(water_normalmap, vec2(waterTex2 * tscale) * windScale) * 2.0 - 1.0;
vec4 vNorm = normalize(nmap0 + nmap2);
//normalmaps
vec4 nmap = texture2D(water_normalmap, vec2(waterTex1 + disdis * sca2) * windScale) * 2.0 - 1.0;
vec4 nmap1 = texture2D(perlin_normalmap, vec2(waterTex1 + disdis * sca2) * windScale) * 2.0 - 1.0;
rotationmatrix(radians(3.0 * sin(osg_SimulationTime * 0.0075)), RotationMatrix);
nmap += texture2D(water_normalmap, vec2(waterTex2 * RotationMatrix * tscale) * windScale) * 2.0 - 1.0;
nmap1 += texture2D(perlin_normalmap, vec2(waterTex2 * RotationMatrix * tscale) * windScale) * 2.0 - 1.0;
nmap *= windEffect_low;
nmap1 *= windEffect_low;
// mix water and noise, modulated by factor
vec4 vNorm = normalize(mix(nmap, nmap1, 0.3) * waveRoughness);
vNorm = -vNorm; //dds fix
//load reflection
vec4 tmp = vec4(lightdir, 0.0);
@ -92,16 +123,32 @@ void main(void)
refl.a *= 1.0;
}
vec3 N0 = vec3(texture2D(water_normalmap, vec2(waterTex1+ disdis*sca2) * windScale) * 2.0 - 1.0);
vec3 N1 = vec3(texture2D(water_normalmap, vec2(waterTex2 * tscale) * windScale) * 2.0 - 1.0);
vec3 N = normalize(normal+N0+N1);
vec3 N0 = vec3(texture2D(water_normalmap, vec2(waterTex1 + disdis * sca2) * windScale) * 2.0 - 1.0);
vec3 N1 = vec3(texture2D(perlin_normalmap, vec2(waterTex1 + disdis * sca) * windScale) * 2.0 - 1.0);
N0 += vec3(texture2D(water_normalmap, vec2(waterTex2 * tscale) * windScale) * 2.0 - 1.0);
N1 += vec3(texture2D(perlin_normalmap, vec2(waterTex2 * tscale) * windScale) * 2.0 - 1.0);
rotationmatrix(radians(2.0 * sin(osg_SimulationTime * 0.005)), RotationMatrix);
N0 += vec3(texture2D(water_normalmap, vec2(waterTex2 * RotationMatrix * (tscale + sca2)) * windScale) * 2.0 - 1.0);
N1 += vec3(texture2D(perlin_normalmap, vec2(waterTex2 * RotationMatrix * (tscale + sca2)) * windScale) * 2.0 - 1.0);
rotationmatrix(radians(-4.0 * sin(osg_SimulationTime * 0.003)), RotationMatrix);
N0 += vec3(texture2D(water_normalmap, vec2(waterTex1 * RotationMatrix + disdis * sca2) * windScale) * 2.0 - 1.0);
N1 += vec3(texture2D(perlin_normalmap, vec2(waterTex1 * RotationMatrix + disdis * sca) * windScale) * 2.0 - 1.0);
N0 *= windEffect_low;
N1 *= windEffect_low;
vec3 N = normalize(mix(Normal + N0 , Normal + N1, 0.3) * waveRoughness);
N = -N; //dds fix
// specular
vec3 specular_color = vec3(gl_LightSource[0].diffuse)
* pow(max(0.0, dot(N, H)), water_shininess) * 6.0;
vec4 specular = vec4(specular_color, 0.5);
specular = specular * saturation * 0.4;
specular = specular * saturation * 0.3 ;
//calculate fresnel
vec4 invfres = vec4( dot(vNorm, viewt) );
@ -121,25 +168,20 @@ void main(void)
vec4 ambient_light = gl_LightSource[0].diffuse;
vec4 finalColor;
// cover = 0;
if(cover >= 1.5){
finalColor = refl + specular;
} else {
finalColor = refl;
}
if (windEffect >= 10.0){
float windScale3 = pow(windScale, 3);
if (N.g >= 0.0005 + 0.085 * windScale3){
vec4 foam_texel = texture2D(sea_foam, vec2(waterTex1+ disdis*sca2) * windScale3 * 50.0);
finalColor = mix(finalColor, max(finalColor, foam_texel), smoothstep(0.0005 + 0.085 * windScale3, 0.1, N.g));
float foamSlope = 0.1 + 0.1 * windScale;
if (windEffect >= 10.0)
if (N.g >= foamSlope){
vec4 foam_texel = texture2D(sea_foam, vec2(waterTex2 * tscale) * 30.0);
finalColor = mix(finalColor, max(finalColor, finalColor + foam_texel), smoothstep(foamSlope, 0.25, N.g));
}
}
finalColor *= ambient_light;
finalColor *= ambient_light;
gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor);
gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor);
}

View file

@ -2,6 +2,8 @@
// http://www.bonzaisoftware.com/water_tut.html and its glsl conversion
// available at http://forum.bonzaisoftware.com/viewthread.php?tid=10
// © Michael Horsch - 2005
// Major update and revisions - 2011-10-07
// © Emilian Huminiuc and Vivian Meazza
#version 120
@ -9,36 +11,48 @@ varying vec4 waterTex1;
varying vec4 waterTex2;
varying vec4 waterTex4;
varying vec4 ecPosition;
uniform float osg_SimulationTime;
uniform float WindE, WindN;
varying vec3 viewerdir;
varying vec3 lightdir;
varying vec3 normal;
uniform float osg_SimulationTime;
uniform float WindE, WindN;
/////// functions /////////
void rotationmatrix(in float angle, out mat4 rotmat)
{
rotmat = mat4( cos( angle ), -sin( angle ), 0.0, 0.0,
sin( angle ), cos( angle ), 0.0, 0.0,
0.0 , 0.0 , 1.0, 0.0,
0.0 , 0.0 , 0.0, 1.0 );
}
void main(void)
{
vec3 N = normalize(gl_Normal);
normal = N;
mat4 RotationMatrix;
vec3 N = normalize(gl_Normal);
normal = N;
ecPosition = gl_ModelViewMatrix * gl_Vertex;
ecPosition = gl_ModelViewMatrix * gl_Vertex;
viewerdir = vec3(gl_ModelViewMatrixInverse[3]) - vec3(gl_Vertex);
lightdir = normalize(vec3(gl_ModelViewMatrixInverse * gl_LightSource[0].position));
viewerdir = vec3(gl_ModelViewMatrixInverse[3]) - vec3(gl_Vertex);
lightdir = normalize(vec3(gl_ModelViewMatrixInverse * gl_LightSource[0].position));
waterTex4 = vec4( ecPosition.xzy, 0.0 );
waterTex4 = vec4( ecPosition.xzy, 0.0 );
vec4 t1 = vec4(0.0, osg_SimulationTime * 0.005217, 0.0, 0.0);
vec4 t2 = vec4(0.0, osg_SimulationTime * -0.0012, 0.0, 0.0);
vec4 t1 = vec4(0.0, osg_SimulationTime * 0.005217, 0.0, 0.0);
vec4 t2 = vec4(0.0, osg_SimulationTime * -0.0012, 0.0, 0.0);
//float windFactor = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.3;
float windFactor = 0.001;
float windFactor = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.01;
float Angle = atan(-WindN + 0.001, WindE + 0.001) - atan(1.0);
waterTex1 = gl_MultiTexCoord0 + t1;
waterTex1.x += WindE * windFactor;
waterTex1.y += WindN * windFactor;
waterTex2 = gl_MultiTexCoord0 + t2;
waterTex2.x += WindE * windFactor;
waterTex2.y += WindN * windFactor;
rotationmatrix(Angle, RotationMatrix);
waterTex1 = gl_MultiTexCoord0 * RotationMatrix - t1 * windFactor;
gl_Position = ftransform();
rotationmatrix(Angle, RotationMatrix);
waterTex2 = gl_MultiTexCoord0 * RotationMatrix - t2 * windFactor;
gl_Position = ftransform();
}

Binary file not shown.

BIN
Textures/Water/sea_foam.dds Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Textures/Water/waves2.dds Normal file

Binary file not shown.

View file

@ -1273,6 +1273,11 @@ Started September 2000 by David Megginson, david@megginson.com
</jetways_edit>
</nasal>
<scenery>
<share-events type="bool" userarchive="y">false</share-events>
<events type="string"/>
</scenery>
</PropertyList>
<!-- end of preferences.xml -->