Switch clouds to shaders.

This commit is contained in:
Quantum 2018-08-26 18:11:18 -04:00
parent 3770ec617b
commit f7797949d9
9 changed files with 107 additions and 32 deletions

View file

@ -5,7 +5,7 @@ from pyglet.gl import *
# noinspection PyUnresolvedReferences
from six.moves import range
from punyverse.glgeom import compile, glRestore, belt, Sphere, Disk, OrbitVBO, Matrix4f, SimpleSphere, TangentSphere
from punyverse.glgeom import compile, glRestore, belt, Disk, OrbitVBO, Matrix4f, SimpleSphere, TangentSphere
from punyverse.model import load_model, WavefrontVBO
from punyverse.orbit import KeplerOrbit
from punyverse.texture import get_best_texture, load_clouds
@ -32,9 +32,14 @@ class Entity(object):
def mv_matrix(self):
return self.world.view_matrix() * self.model_matrix
@cached_property
def mvp_matrix(self):
return self.world.vp_matrix * self.model_matrix
def update(self):
self.model_matrix = None
self.mv_matrix = None
self.mvp_matrix = None
x, y, z = self.location
dx, dy, dz = self.direction
self.location = x + dx, y + dy, z + dz
@ -316,8 +321,9 @@ class SphericalBody(Body):
atm_texture = atmosphere_data.get('diffuse_texture', None)
cloud_texture = atmosphere_data.get('cloud_texture', None)
if cloud_texture is not None:
self.cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
self.clouds = Sphere(self.radius + 2, division, division)
self.cloud_transparency = get_best_texture(cloud_texture, loader=load_clouds)
self.cloud_radius = self.radius + 2
self.clouds = self._get_sphere(division, tangent=False)
if atm_texture is not None:
self.atm_texture = get_best_texture(atm_texture, clamp=True)
@ -341,7 +347,7 @@ class SphericalBody(Body):
shader.uniform_float('u_radius', self.radius)
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
shader.uniform_mat4('u_mvpMatrix', self.world.vp_matrix * self.model_matrix)
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, self.texture)
@ -395,7 +401,7 @@ class SphericalBody(Body):
def _draw_star(self):
shader = self.world.activate_shader('star')
shader.uniform_float('u_radius', self.radius)
shader.uniform_mat4('u_mvpMatrix', self.world.vp_matrix * self.model_matrix)
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, self.texture)
@ -436,17 +442,30 @@ class SphericalBody(Body):
self.atmosphere.draw()
def _draw_clouds(self):
with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
glLoadMatrixf(self.mv_matrix)
glEnable(GL_BLEND)
glEnable(GL_ALPHA_TEST)
glEnable(GL_CULL_FACE)
glDisable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
glEnable(GL_BLEND)
shader = self.world.activate_shader('clouds')
shader.uniform_float('u_radius', self.cloud_radius)
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
glCullFace(GL_BACK)
glBindTexture(GL_TEXTURE_2D, self.cloud_texture)
self.clouds.draw()
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, self.cloud_transparency)
shader.uniform_texture('u_transparency', 0)
shader.uniform_vec3('u_diffuse', 1, 1, 1)
shader.uniform_vec3('u_ambient', 0.1, 0.1, 0.1)
glBindBuffer(GL_ARRAY_BUFFER, self.clouds.vbo)
shader.vertex_attribute('a_normal', self.clouds.direction_size, self.clouds.type, GL_FALSE,
self.clouds.stride, self.clouds.direction_offset)
shader.vertex_attribute('a_uv', self.clouds.uv_size, self.clouds.type, GL_FALSE,
self.clouds.stride, self.clouds.uv_offset)
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.clouds.vertex_count)
shader.deactivate_attributes()
glBindBuffer(GL_ARRAY_BUFFER, 0)
self.world.activate_shader(None)
glDisable(GL_BLEND)
def _draw_rings(self):
with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):

View file

@ -1,4 +1,5 @@
import os
import sys
from ctypes import pointer, byref, create_string_buffer, POINTER, cast
from pyglet.gl import *
@ -39,11 +40,15 @@ class Program(object):
succeeded = GLint()
log_length = GLint()
glGetShaderiv(shader, GL_COMPILE_STATUS, byref(succeeded))
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(log_length))
buffer = create_string_buffer(log_length.value + 1)
glGetShaderInfoLog(shader, log_length.value, None, buffer)
if not succeeded:
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(log_length))
buffer = create_string_buffer(log_length.value + 1)
glGetShaderInfoLog(shader, log_length.value, None, buffer)
raise CompileError(buffer.value)
raise CompileError(buffer.value.decode('utf-8'))
elif log_length.value:
print('Warning:', file=sys.stderr)
print(buffer.value.decode('utf-8'), file=sys.stderr)
def __init__(self, vertex_file, fragment_file):
with glShader(GL_VERTEX_SHADER) as vertex_shader, glShader(GL_FRAGMENT_SHADER) as fragment_shader:

View file

@ -0,0 +1,19 @@
#version 130
in vec2 v_uv;
in vec3 v_normal;
in vec3 v_position;
out vec4 o_fragColor;
uniform vec3 u_ambient;
uniform vec3 u_diffuse;
uniform vec3 u_sun;
uniform sampler2D u_transparency;
void main() {
vec3 incident = normalize(u_sun - v_position);
vec3 diffuse = u_diffuse * clamp(dot(v_normal, incident) + 0.2, 0.0, 1.0);
o_fragColor = vec4(u_ambient + diffuse, texture(u_transparency, v_uv).r);
}

View file

@ -0,0 +1,20 @@
#version 130
in vec3 a_normal;
in vec2 a_uv;
out vec2 v_uv;
out vec3 v_normal;
out vec3 v_position;
uniform float u_radius;
uniform mat4 u_mvpMatrix;
uniform mat4 u_modelMatrix;
void main() {
vec3 position = u_radius * a_normal;
v_uv = a_uv;
v_normal = (u_modelMatrix * vec4(a_normal, 0)).xyz;
v_position = (u_modelMatrix * vec4(position, 1)).xyz;
gl_Position = u_mvpMatrix * vec4(position, 1);
}

View file

@ -6,6 +6,8 @@ in vec3 v_position;
in vec3 v_camDirection;
in mat3 v_TBN;
out vec4 o_fragColor;
struct Surface {
sampler2D diffuseMap;
bool hasNormal;
@ -49,5 +51,5 @@ void main() {
emission *= u_planet.emission * (1 - min(diffuseIntensity * 2, 1));
specular *= u_planet.specular * u_sun.specular * max(shininess, 0) * diffuseIntensity;
gl_FragColor = vec4((ambient + diffuse + emission + specular) * u_sun.intensity, 1);
o_fragColor = vec4((ambient + diffuse + emission + specular) * u_sun.intensity, 1);
}

View file

@ -1,8 +1,9 @@
#version 130
in vec2 v_uv;
out vec4 o_fragColor;
uniform sampler2D u_skysphere;
void main() {
gl_FragColor = vec4(texture(u_skysphere, v_uv).rgb, 1);
o_fragColor = vec4(texture(u_skysphere, v_uv).rgb, 1);
}

View file

@ -1,8 +1,9 @@
#version 130
in vec2 v_uv;
out vec4 o_fragColor;
uniform sampler2D u_emission;
void main() {
gl_FragColor = vec4(texture(u_emission, v_uv).rgb, 1);
o_fragColor = vec4(texture(u_emission, v_uv).rgb, 1);
}

View file

@ -1,6 +1,5 @@
from __future__ import print_function
import itertools
import os.path
import struct
from ctypes import c_int, byref, c_uint
@ -9,7 +8,7 @@ from io import BytesIO
import six
from pyglet import image
from pyglet.gl import *
from six.moves import zip, range
from six.moves import range
try:
from ._glgeom import bgr_to_rgb, flip_vertical
@ -229,21 +228,26 @@ def load_clouds(file):
path, width, height, depth, mode, texture = load_image(file, path)
if depth != 1:
texture = texture[::depth]
buffer = c_uint()
glGenTextures(1, byref(buffer))
id = buffer.value
pixels = bytearray(len(texture) * 4)
white = b'\xff'[0]
pixels[:] = itertools.chain.from_iterable(zip(itertools.repeat(white), itertools.repeat(white),
itertools.repeat(white),
itertools.islice(texture, 0, None, depth)))
glBindTexture(GL_TEXTURE_2D, id)
if gl_info.have_version(3) or gl_info.have_extension('GL_ARB_framebuffer_object'):
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, texture)
glGenerateMipmap(GL_TEXTURE_2D)
else:
gluBuild2DMipmaps(GL_TEXTURE_2D, 1, width, height, GL_RED, GL_UNSIGNED_BYTE, texture)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, six.binary_type(pixels))
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
if gl_info.have_extension('GL_EXT_texture_filter_anisotropic'):
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glGetInteger(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT))
cache[path] = id
return id

View file

@ -20,6 +20,7 @@ class World(object):
PROGRAMS = {
'sky': ('sky.vertex.glsl', 'sky.fragment.glsl'),
'planet': ('planet.vertex.glsl', 'planet.fragment.glsl'),
'clouds': ('clouds.vertex.glsl', 'clouds.fragment.glsl'),
'star': ('star.vertex.glsl', 'star.fragment.glsl'),
}
@ -52,6 +53,9 @@ class World(object):
shader.uniform_vec3('u_sun.specular', 0.5, 0.5, 0.5)
shader.uniform_vec3('u_sun.position', 0, 0, 0)
shader.uniform_float('u_sun.intensity', 1)
shader = self.activate_shader('clouds')
shader.uniform_vec3('u_sun', 0, 0, 0)
self.activate_shader(None)
def _load_programs(self):