Shuvit game master repo. http://shuvit.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

__init__.py 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. from ... import ShaderMaterial
  2. from ... import ReadFile
  3. from mathutils import Vector
  4. from mathutils import Matrix
  5. import time
  6. import math
  7. import bge
  8. import bgl
  9. class Water(ShaderMaterial):
  10. '''The original work for this material comes from Martinsh:
  11. > http://devlog-martinsh.blogspot.ca/'''
  12. FragmentShader = ReadFile('./water.fs', __file__)
  13. VertexShader = ReadFile('./water.vs', __file__)
  14. # Parameters
  15. backgroundColor = Vector((.1, .2, .8, .0))
  16. waterCamera = property(
  17. lambda self: self.owner.children.get('WaterRenderCamera'))
  18. activeCamera = property(
  19. lambda self: self.owner.scene.active_camera)
  20. height = property(
  21. lambda self: bge.render.getWindowHeight())
  22. width = property(
  23. lambda self: bge.render.getWindowWidth())
  24. reflectionSize = 512
  25. refractionSize = 512
  26. timeModulo = 1 << 16
  27. offset = -0.2
  28. def init(self):
  29. # Setting up the reflection texture
  30. self.reflection = bge.texture.Texture(self.owner, 0, 0)
  31. self.reflection.source = bge.texture.ImageRender(
  32. self.owner.scene, self.waterCamera)
  33. self.reflection.source.capsize = (
  34. self.width, self.height)
  35. # self.reflectionSize, self.reflectionSize)
  36. # self.reflectionSize // 2, self.reflectionSize // 2)
  37. self.reflection.source.background = list(
  38. 255 * self.backgroundColor)
  39. self.reflection.refresh(True)
  40. # Setting up the refraction texture
  41. self.refraction = bge.texture.Texture(self.owner, 0, 1)
  42. self.refraction.source = bge.texture.ImageRender(
  43. self.owner.scene, self.waterCamera)
  44. self.refraction.source.capsize = (
  45. self.width, self.height)
  46. # self.refractionSize, self.refractionSize)
  47. # self.refractionSize // 2, self.refractionSize // 2)
  48. self.refraction.source.background = list(
  49. 255 * self.backgroundColor)
  50. self.refraction.refresh(True)
  51. def pre_draw_setup(self, shader):
  52. '''I have no idea why, but this has to run on pre_draw_setup...'''
  53. shader.setAttrib(bge.logic.SHD_TANGENT)
  54. shader.setUniformDef('ModelMatrix', bge.logic.MODELMATRIX)
  55. shader.setUniformDef('cameraPos', bge.logic.CAM_POS)
  56. shader.setSampler('reflectionSampler', 0)
  57. shader.setSampler('refractionSampler', 1)
  58. shader.setSampler('normalSampler', 2)
  59. shader.setSampler('depthSampler', 3)
  60. shader.setUniform1f('timer',
  61. (3 * time.time()) % self.timeModulo)
  62. # User uniforms
  63. shader.setUniform1f('scale', self.owner.get('water.scale', 1.))
  64. shader.setUniform1f('windSpeed', self.owner.get('water.wind.speed', .2))
  65. self.watertexture()
  66. def watertexture(self):
  67. waterCamera = self.waterCamera
  68. activeCamera = self.activeCamera
  69. # Setting up the water camera parameters
  70. waterCamera.lens = activeCamera.lens
  71. waterCamera.projection_matrix = activeCamera.projection_matrix
  72. self.owner.visible = False
  73. # plane normals Z = Front
  74. normal = self.owner.getAxisVect((0., 0., 1.))
  75. # closest distance from center to plane
  76. distance = -self.owner.position.project(normal).magnitude
  77. # VdotN to get front-face/back-face
  78. V = (activeCamera.position - self.owner.position
  79. ).normalized().dot(normal)
  80. # Invert normals when back-face (?)
  81. if V < 0: normal = -normal
  82. # Processing the reflection and the refraction
  83. self.processReflection(activeCamera, waterCamera, normal, distance)
  84. self.processRefraction(activeCamera, waterCamera, normal, distance)
  85. self.owner.visible = True
  86. def processReflection(self, activeCamera, waterCamera, normal, distance):
  87. '''This is the refactored way of processing reflection'''
  88. M1 = Matrix(self.owner.orientation)
  89. M2 = Matrix(self.owner.orientation)
  90. M2.invert()
  91. R = Matrix.Rotation(math.radians(180), 3, 'Y')
  92. U = Matrix.Scale(-1, 3, Vector((1, 0, 0)))
  93. position = (activeCamera.position - self.owner.position) * M1
  94. position = self.owner.position + position * R * U * M2
  95. orientation = Matrix(activeCamera.orientation)
  96. orientation.transpose()
  97. orientation = orientation * M1 * R * U * M2
  98. orientation.transpose()
  99. # Orienting and positioning the water camera
  100. waterCamera.orientation = orientation
  101. waterCamera.position = position
  102. # Culling front faces as the camera is scaled to -1 (?)
  103. bgl.glCullFace(bgl.GL_FRONT)
  104. # Changing clipping plane
  105. plane = bgl.Buffer(bgl.GL_DOUBLE, [4], (
  106. -normal[0], -normal[1], -normal[2], -distance + self.offset))
  107. bgl.glClipPlane(bgl.GL_CLIP_PLANE0, plane)
  108. bgl.glEnable(bgl.GL_CLIP_PLANE0)
  109. self.reflection.refresh(True)
  110. # Reverting parameters
  111. bgl.glCullFace(bgl.GL_BACK)
  112. bgl.glDisable(bgl.GL_CLIP_PLANE0)
  113. def processRefraction(self, activeCamera, waterCamera, normal, distance):
  114. '''This is the refactored way of processing refraction'''
  115. orientation = Matrix(activeCamera.orientation)
  116. position = activeCamera.position
  117. # Orienting and positioning the water camera
  118. waterCamera.orientation = orientation
  119. waterCamera.position = position
  120. # Changing clipping plane
  121. plane = bgl.Buffer(bgl.GL_DOUBLE, [4], (
  122. normal[0], normal[1], normal[2], -distance + self.offset))
  123. bgl.glClipPlane(bgl.GL_CLIP_PLANE1, plane)
  124. bgl.glEnable(bgl.GL_CLIP_PLANE1)
  125. self.refraction.refresh(True)
  126. bgl.glDisable(bgl.GL_CLIP_PLANE1)