Skip to content

Instantly share code, notes, and snippets.

@ethanaeris
Last active November 2, 2020 18:13
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ethanaeris/0419452358adc1abcf92ffb263937346 to your computer and use it in GitHub Desktop.
Save ethanaeris/0419452358adc1abcf92ffb263937346 to your computer and use it in GitHub Desktop.
Fast OCean - Eevee Branch
# -*- coding: utf-8 -*-
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "Fast Ocean",
"author": "Laurent Laget",
"version": (0, 9,5),
"blender": (2, 78, 0),
"location": "Add > Mesh",
"description": "Create a dynamic ocean and turn any object easily into a collider",
"warning": "",
"wiki_url": "",
"category": "Add Mesh",
}
import bpy
def main(context):
for ob in context.scene.objects:
print(ob)
#classe fastocean
class fastocean(bpy.types.Operator):
"""Create a dynamic ocean"""
bl_idname = "object.fastocean"
bl_label = "fastocean"
bl_options = {'REGISTER', 'UNDO'}
def invoke(self, context, event):
#Create light probe for irradiance optionnal
bpy.ops.object.lightprobe_add(type='GRID')
bpy.ops.transform.resize(value=(30, 30, 30), constraint_axis=(False, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
bpy.context.object.name = "Irradiance probe"
#create reflection probe optionnal
bpy.ops.object.lightprobe_add(type='SPHERE', view_align=False, enter_editmode=False, location=(0, 0, 0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False))
#ground creation
bpy.ops.mesh.primitive_plane_add(radius=30, view_align=False, enter_editmode=False, location=(0, 0, -25), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False))
bpy.context.object.name = "Ground"
bpy.ops.transform.resize(value=(2, 2, 2), constraint_axis=(False, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
#creation water plane
bpy.ops.mesh.primitive_plane_add()
#name and creation modifier ocean
bpy.context.object.name = "Ocean"
bpy.ops.object.modifier_add(type='OCEAN')
#setup modifier ocean
bpy.context.object.modifiers["Ocean"].repeat_x = 1
bpy.context.object.modifiers["Ocean"].repeat_y = 1
bpy.context.object.modifiers["Ocean"].resolution = 12
bpy.context.object.modifiers["Ocean"].wave_scale = 2
bpy.context.object.modifiers["Ocean"].use_normals = True
bpy.context.object.modifiers["Ocean"].use_foam = True
bpy.context.object.modifiers["Ocean"].foam_layer_name = "foam_layer"
obj = bpy.context.active_object
#creation material
mat_name = "M_ocean"
materials = bpy.data.materials
mat = materials.get(mat_name) or materials.new(mat_name)
if mat is None:
mat = bpy.data.materials.new(name="M_ocean")
if obj.data.materials:
obj.data.materials[0] = mat
else:
obj.data.materials.append(mat)
###creation shader###
mat.use_nodes = True
nodes = mat.node_tree.nodes
mat = materials.get(mat_name) or materials.new(mat_name)
for node in nodes:
nodes.remove(node)
#node blue water
water_node = nodes.new('ShaderNodeBsdfPrincipled')
water_node.location = (80,50)
#water_node.inputs[0].default_value = (0.11,0.44,0.8,1)
water_node.inputs[4].default_value = (0.465)
water_node.inputs[5].default_value = (0.091)
water_node.inputs[7].default_value = (0.200)
water_node.inputs[14].default_value = (1.33)
water_node.inputs[15].default_value = (0.9)
water_node.label = ('Eevee BSDF')
#emission shader to mix with principled
emission_node = nodes.new('ShaderNodeEmission')
emission_node.inputs[1].default_value = (1.5)
emission_node.location = (80,700)
#mix node 3 to mix principled with emission
mix_node_emission = nodes.new('ShaderNodeMixShader')
mix_node_emission.location = (250,600)
mix_node_emission.label = ('Mix Node Emission')
### nodes for foam, attribute and noise
#foam attribute for both shaders
foam_node = nodes.new('ShaderNodeAttribute')
foam_node.location = (-450,300)
foam_node.attribute_name = ('foam_layer')
foam_node.label = ('Foam Attribute')
### nodes for water, bump and volume
#texture noise for bump
noise_node = nodes.new('ShaderNodeTexNoise')
noise_node.inputs[1].default_value = (5)
noise_node.location = (-700,50)
#gradient water
gradient_water_node = nodes.new(type='ShaderNodeValToRGB')
gradient_water_node.location = (-530,50)
gradient_water_node.color_ramp.elements[0].color = (1, 1, 1, 1)
gradient_water_node.color_ramp.elements[1].color = (0, 0, 0, 1)
#vector bump node
bump_water_node = nodes.new('ShaderNodeBump')
bump_water_node.location = (-250,50)
#mix foam with blue color
mix_node_foam = nodes.new('ShaderNodeMixRGB')
mix_node_foam.inputs[2].default_value = (0, 0.494436, 0.5, 1)
mix_node_foam.location = (-270,300)
#mix foam with blue color 2
mix_node_foam2 = nodes.new('ShaderNodeMixRGB')
mix_node_foam2.inputs[2].default_value = (0.218349, 0.545644, 0.8, 1)
mix_node_foam2.location = (-100,300)
#node output
node_output = nodes.new(type='ShaderNodeOutputMaterial')
node_output.location = 600,100
node_output.label = ('Output Eevee')
###creation of links###
### Links for water ###
#link main shader to output
mat.node_tree.links.new(mix_node_emission.outputs[0], node_output.inputs['Surface'])
#link foam paint attribute to first mix
mat.node_tree.links.new(foam_node.outputs[0], mix_node_foam.inputs[1])
#link foam paint attribute to second mix
mat.node_tree.links.new(foam_node.outputs[0], mix_node_foam2.inputs[0])
#link foam attribute to emission slot of main shader
#mat.node_tree.links.new(foam_node.outputs[0], water_node.inputs[4])
#link foam attribute to emission shader
mat.node_tree.links.new(foam_node.outputs[0], emission_node .inputs[0])
#link foam attribute to mix factor shader
mat.node_tree.links.new(foam_node.outputs[0], mix_node_emission.inputs[0])
#link first mix to second mix
mat.node_tree.links.new(mix_node_foam.outputs[0], mix_node_foam2.inputs[1])
#link second mix to color of main shader
mat.node_tree.links.new(mix_node_foam2.outputs[0], water_node.inputs[0])
#emission to mix shader 3
mat.node_tree.links.new(emission_node.outputs[0], mix_node_emission.inputs[2])
#link principled to mix shader 3
mat.node_tree.links.new(water_node.outputs['BSDF'], mix_node_emission.inputs[1])
#link noise to color ramp
mat.node_tree.links.new(noise_node.outputs[0], gradient_water_node.inputs[0])
#link color ramp to vector bump
mat.node_tree.links.new(gradient_water_node.outputs[0], bump_water_node.inputs[2])
#link vector bump to main shader
mat.node_tree.links.new(bump_water_node.outputs[0], water_node.inputs[17])
bpy.context.object.active_material.blend_method = 'BLEND'
###apply dynamic paint and setup the ocean as a canvas###
bpy.ops.object.modifier_add(type='DYNAMIC_PAINT')
bpy.ops.dpaint.type_toggle(type='CANVAS')
bpy.context.object.modifiers["Dynamic Paint"].canvas_settings.canvas_surfaces["Surface"].preview_id = 'WETMAP'
bpy.context.object.modifiers["Dynamic Paint"].canvas_settings.canvas_surfaces["Surface"].use_dissolve = True
bpy.ops.dpaint.output_toggle(output='A')
bpy.ops.dpaint.output_toggle(output='B')
bpy.context.object.modifiers["Dynamic Paint"].canvas_settings.canvas_surfaces["Surface"].use_antialiasing = True
###apply a second layer of dynamic paint with a wave effect###
bpy.ops.dpaint.surface_slot_add()
bpy.context.object.modifiers["Dynamic Paint"].canvas_settings.canvas_surfaces["Surface.001"].name = "onde"
bpy.context.object.modifiers["Dynamic Paint"].canvas_settings.canvas_surfaces["onde"].surface_type = 'WAVE'
bpy.context.object.modifiers["Dynamic Paint"].canvas_settings.canvas_surfaces["onde"].use_antialiasing = True
bpy.context.object.modifiers["Dynamic Paint"].canvas_settings.canvas_surfaces["onde"].use_wave_open_border = True
return {'FINISHED'}
#classe collider_ocean
class collider_ocean(bpy.types.Operator):
"""Transform the selected object easily into a collider"""
bl_idname = "object.collider_ocean"
bl_label = "collider_ocean"
bl_options = {'REGISTER', 'UNDO'}
def invoke(self, context, event):
#apply dynamic paint, and setup the object as a brush
bpy.ops.object.modifier_add(type='DYNAMIC_PAINT')
bpy.context.object.modifiers["Dynamic Paint"].ui_type = 'BRUSH'
bpy.ops.dpaint.type_toggle(type='BRUSH')
bpy.context.object.modifiers["Dynamic Paint"].brush_settings.paint_source = 'VOLUME_DISTANCE'
bpy.context.object.modifiers["Dynamic Paint"].brush_settings.paint_distance = 4
bpy.context.object.modifiers["Dynamic Paint"].brush_settings.wave_factor = 2
return {'FINISHED'}
def menu_item(self, context):
self.layout.operator(fastocean.bl_idname, text="fast ocean", icon="PLUGIN")
self.layout.operator(collider_ocean.bl_idname, text="Make object collide with ocean", icon="PLUGIN")
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_mesh_add.append(menu_item)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_mesh_add.remove(menu_item)
if __name__ == "__main__":
register()
@JohnRWMarchant
Copy link

I hope we can get an update for Blender 2.8, i get an error when loading it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment