Faster and smaller vertex data

This commit is contained in:
luboslenco 2018-12-14 15:27:43 +01:00
parent 914030e7f4
commit 975f995796
28 changed files with 417 additions and 362 deletions

View file

@ -9,11 +9,16 @@
#endif
#ifdef _ShadowMap
#ifdef _SinglePoint
const int shadowMapCount = 1;
#else
const int shadowMapCount = 4;
#endif
uniform vec2 lightProj;
// uniform samplerCubeShadow shadowMapPoint[4]; //arm_dev
uniform samplerCube shadowMapPoint[4];
// uniform samplerCubeShadow shadowMapPoint[shadowMapCount]; //arm_dev
uniform samplerCube shadowMapPoint[shadowMapCount];
#ifdef _Spot
uniform sampler2D shadowMapSpot[4];
uniform sampler2D shadowMapSpot[shadowMapCount];
uniform mat4 LWVPSpot0;
uniform mat4 LWVPSpot1;
uniform mat4 LWVPSpot2;
@ -51,6 +56,10 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
direct *= smoothstep(spotB, spotA, spotEffect);
}
#ifdef _ShadowMap
#ifdef _SinglePoint
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias, shadowmapSize);
#else
if (index == 0) {
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias, shadowmapSize);
@ -68,6 +77,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias, shadowmapSize);
}
#endif
#endif
return direct;
}
#endif
@ -95,12 +105,15 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
// #endif
#ifdef _ShadowMap
// Oh well..
#ifdef _SinglePoint
direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
#else
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#endif
#endif
return direct;
}

View file

@ -62,7 +62,7 @@ class RenderPathRaytracer {
structure.add("nor", VertexData.Float3);
var geom = iron.Scene.active.meshes[0].data.geom;
var vb = new VertexBuffer(Std.int(geom.positions.length / 3), structure, kha.graphics5.Usage.StaticUsage);
var vb = new VertexBuffer(Std.int(geom.positions.length / 4), structure, kha.graphics5.Usage.StaticUsage);
var vba = vb.lock();
iron.data.Geometry.buildVertices(vba, geom.positions, geom.normals);
vb.unlock();

View file

@ -141,16 +141,16 @@ class Cycles {
if (frag.wposition) {
vert.add_uniform('mat4 W', '_worldMatrix');
vert.add_out('vec3 wposition');
vert.write_attrib('wposition = vec4(W * vec4(pos, 1.0)).xyz;');
vert.write_attrib('wposition = vec4(W * vec4(pos.xyz, 1.0)).xyz;');
}
else if (vert.wposition) {
vert.add_uniform('mat4 W', '_worldMatrix');
vert.write_attrib('vec3 wposition = vec4(W * vec4(pos, 1.0)).xyz;');
vert.write_attrib('vec3 wposition = vec4(W * vec4(pos.xyz, 1.0)).xyz;');
}
if (frag.vposition) {
vert.add_uniform('mat4 WV', '_worldViewMatrix');
vert.add_out('vec3 vposition');
vert.write_attrib('vposition = vec4(WV * vec4(pos, 1.0)).xyz;');
vert.write_attrib('vposition = vec4(WV * vec4(pos.xyz, 1.0)).xyz;');
}
if (frag.mposition) {
vert.add_out('vec3 mposition');
@ -162,7 +162,7 @@ class Cycles {
}
}
if (frag.wtangent) {
con.add_elem('tang', 3);
con.add_elem('tang', 'short4norm');
vert.add_uniform('mat3 N', '_normalMatrix');
vert.add_out('vec3 wtangent');
vert.write_attrib('wtangent = normalize(N * tang);');
@ -170,7 +170,7 @@ class Cycles {
if (frag.vVecCam) {
vert.add_uniform('mat4 WV', '_worldViewMatrix');
vert.add_out('vec3 eyeDirCam');
vert.write_attrib('eyeDirCam = vec4(WV * vec4(pos, 1.0)).xyz; eyeDirCam.z *= -1.0;');
vert.write_attrib('eyeDirCam = vec4(WV * vec4(pos.xyz, 1.0)).xyz; eyeDirCam.z *= -1.0;');
frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);');
}
if (frag.vVec) {
@ -437,12 +437,12 @@ class Cycles {
if (node.type == 'ATTRIBUTE') {
if (socket == node.outputs[0]) { // Color
curshader.context.add_elem('col', 3); // Vcols only for now
curshader.context.add_elem('col', 'short4norm'); // Vcols only for now
// return 'vcolor';
return 'vec3(0.0)';
}
else { // Vector
curshader.context.add_elem('tex', 2); // UVMaps only for now
curshader.context.add_elem('tex', 'short2norm'); // UVMaps only for now
// mat = mat_get_material()
// mat_users = mat_get_material_users()
// if mat_users != None and mat in mat_users:
@ -451,7 +451,7 @@ class Cycles {
// lays = mat_user.data.uv_layers
// # Second uvmap referenced
// if len(lays) > 1 and node.attribute_name == lays[1].name:
// con.add_elem('tex1', 2)
// con.add_elem('tex1', 'short2norm')
// return 'vec3(texCoord1.x, 1.0 - texCoord1.y, 0.0)'
return 'vec3(texCoord.x, 1.0 - texCoord.y, 0.0)';
}
@ -932,7 +932,7 @@ class Cycles {
return 'n';
}
else if (socket == node.outputs[2]) {// UV
curshader.context.add_elem('tex', 2);
curshader.context.add_elem('tex', 'short2norm');
return 'vec3(texCoord.x, 1.0 - texCoord.y, 0.0)';
}
else if (socket == node.outputs[3]) { // Object
@ -954,7 +954,7 @@ class Cycles {
else if (node.type == 'UVMAP') {
//dupli = node.from_dupli
curshader.context.add_elem('tex', 2);
curshader.context.add_elem('tex', 'short2norm');
return 'vec3(texCoord.x, 1.0 - texCoord.y, 0.0)';
}
@ -1127,7 +1127,7 @@ class Cycles {
// if (strength != '1.0') frag.write('n.xy *= $strength;');
// # frag.write('n = normalize(TBN * normalize(n));')
// frag.write('n = TBN * normalize(n);')
// con.add_elem('tang', 3)
// con.add_elem('tang', 'short4norm')
parse_teximage_vector = true;
frag.write_normal--;
@ -1716,7 +1716,7 @@ class Cycles {
public static var texCoordName = 'texCoord';
static function texture_store(node:TNode, tex:TBindTexture, tex_name:String, to_linear = false):String {
matcon.bind_textures.push(tex);
curshader.context.add_elem('tex', 2);
curshader.context.add_elem('tex', 'short2norm');
curshader.add_uniform('sampler2D $tex_name');
var uv_name = '';
if (getInputLink(node.inputs[0]) != null && parse_teximage_vector) {

View file

@ -41,7 +41,7 @@ class CyclesShaderContext {
alpha_blend_operation: props.alpha_blend_operation,
fragment_shader: '',
vertex_shader: '',
vertex_structure: Reflect.hasField(props, 'vertex_structure') ? props.vertex_structure : [ {name: "pos", size: 3}, {name: "nor", size: 3}]
vertex_elements: Reflect.hasField(props, 'vertex_elements') ? props.vertex_elements : [ {name: "pos", data: 'short4norm'}, {name: "nor", data: 'short2norm'}]
};
if (props.color_write_red != null)
@ -65,23 +65,23 @@ class CyclesShaderContext {
constants = data.constants = [];
}
public function add_elem(name:String, size:Int) {
for (e in data.vertex_structure) {
public function add_elem(name:String, data:String) {
for (e in data.vertex_elements) {
if (e.name == name) return;
}
var elem:TVertexData = { name: name, size: size };
data.vertex_structure.push(elem);
var elem:TVertexElement = { name: name, data: data };
data.vertex_elements.push(elem);
}
public function is_elem(name:String) {
for (elem in data.vertex_structure)
for (elem in data.vertex_elements)
if (elem.name == name)
return true;
return false;
}
public function get_elem(name:String):TVertexData {
for (elem in data.vertex_structure) {
public function get_elem(name:String):TVertexElement {
for (elem in data.vertex_elements) {
#if cpp
if (Reflect.field(elem, "name") == name)
#else
@ -259,7 +259,7 @@ class CyclesShader {
function vstruct_to_vsin() {
// if self.shader_type != 'vert' or self.ins != [] or not self.vstruct_as_vsin: # Vertex structure as vertex shader input
// return
var vs = context.data.vertex_structure;
var vs = context.data.vertex_elements;
for (e in vs) {
add_in('vec' + e.size + ' ' + e.name);
}

View file

@ -504,7 +504,7 @@ class ConvexBreaker {
na.push(normal.x);
na.push(normal.y);
na.push(normal.z);
ind.push(Std.int(pa.length / 3 - 1));
ind.push(Std.int(pa.length / 4 - 1));
}
else {
na[fi * 3] = normal.x;

View file

@ -336,7 +336,7 @@ class KinematicCharacterController extends Trait {
var sy = scale.y * (1.0 - margin);
var sz = scale.z * (1.0 - margin);
for (i in 0...Std.int(positions.length / 3)) {
for (i in 0...Std.int(positions.length / 4)) {
vec1.setX(positions[i * 3] * sx);
vec1.setY(positions[i * 3 + 1] * sy);
vec1.setZ(positions[i * 3 + 2] * sz);

View file

@ -97,7 +97,7 @@ class PhysicsHook extends Trait {
#end
var geom = cast(object, MeshObject).data.geom;
var numNodes = Std.int(geom.positions.length / 3);
var numNodes = Std.int(geom.positions.length / 4);
for (i in 0...numNodes) {
var node = nodes.at(i);
#if js

View file

@ -443,11 +443,11 @@ class RigidBody extends iron.Trait {
function fillConvexHull(shape:BtConvexHullShapePointer, scale:Vec4, margin:Float) {
var positions = cast(object, MeshObject).data.geom.positions;
var sx = scale.x * (1.0 - margin);
var sy = scale.y * (1.0 - margin);
var sz = scale.z * (1.0 - margin);
var sx = scale.x * (1.0 - margin) * (1 / 32767);
var sy = scale.y * (1.0 - margin) * (1 / 32767);
var sz = scale.z * (1.0 - margin) * (1 / 32767);
for (i in 0...Std.int(positions.length / 3)) {
for (i in 0...Std.int(positions.length / 4)) {
vec1.setX(positions[i * 3] * sx);
vec1.setY(positions[i * 3 + 1] * sy);
vec1.setZ(positions[i * 3 + 2] * sz);
@ -459,17 +459,21 @@ class RigidBody extends iron.Trait {
var positions = cast(object, MeshObject).data.geom.positions;
var indices = cast(object, MeshObject).data.geom.indices;
var sx = scale.x * (1 / 32767);
var sy = scale.y * (1 / 32767);
var sz = scale.z * (1 / 32767);
for (ar in indices) {
for (i in 0...Std.int(ar.length / 3)) {
vec1.setX(positions[ar[i * 3 + 0] * 3 + 0] * scale.x);
vec1.setY(positions[ar[i * 3 + 0] * 3 + 1] * scale.y);
vec1.setZ(positions[ar[i * 3 + 0] * 3 + 2] * scale.z);
vec2.setX(positions[ar[i * 3 + 1] * 3 + 0] * scale.x);
vec2.setY(positions[ar[i * 3 + 1] * 3 + 1] * scale.y);
vec2.setZ(positions[ar[i * 3 + 1] * 3 + 2] * scale.z);
vec3.setX(positions[ar[i * 3 + 2] * 3 + 0] * scale.x);
vec3.setY(positions[ar[i * 3 + 2] * 3 + 1] * scale.y);
vec3.setZ(positions[ar[i * 3 + 2] * 3 + 2] * scale.z);
vec1.setX(positions[ar[i * 3 + 0] * 3 + 0] * sx);
vec1.setY(positions[ar[i * 3 + 0] * 3 + 1] * sy);
vec1.setZ(positions[ar[i * 3 + 0] * 3 + 2] * sz);
vec2.setX(positions[ar[i * 3 + 1] * 3 + 0] * sx);
vec2.setY(positions[ar[i * 3 + 1] * 3 + 1] * sy);
vec2.setZ(positions[ar[i * 3 + 1] * 3 + 2] * sz);
vec3.setX(positions[ar[i * 3 + 2] * 3 + 0] * sx);
vec3.setY(positions[ar[i * 3 + 2] * 3 + 1] * sy);
vec3.setZ(positions[ar[i * 3 + 2] * 3 + 2] * sz);
triangleMesh.addTriangle(vec1, vec2, vec3);
}
}

View file

@ -90,7 +90,7 @@ class SoftBody extends Trait {
}
var positions = fromF32(geom.positions);
for (i in 0...Std.int(positions.length / 3)) {
for (i in 0...Std.int(positions.length / 4)) {
v.set(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
v.applyQuat(object.transform.rot);
v.x *= object.transform.scale.x;

View file

@ -25,6 +25,7 @@ import arm.material.make as make_material
import arm.material.mat_batch as mat_batch
import arm.make_renderpath as make_renderpath
import arm.material.cycles as cycles
import numpy as np
NodeTypeNode = 0
NodeTypeBone = 1
@ -1362,10 +1363,9 @@ class ArmoryExporter:
else:
self.output['mesh_datas'].append(o)
def make_va(self, attrib, size, values):
def make_va(self, attrib, values):
va = {}
va['attrib'] = attrib
va['size'] = size
va['values'] = values
return va
@ -1383,8 +1383,8 @@ class ArmoryExporter:
has_col = self.get_export_vcols(exportMesh) == True and num_colors > 0
has_tang = self.has_tangents(exportMesh)
vdata = [0] * num_verts * 3
ndata = [0] * num_verts * 3
vdata = [0.0] * num_verts * 3
ndata = [0.0] * num_verts * 3
if has_tex:
# Get active uvmap
t0map = 0
@ -1405,28 +1405,28 @@ class ArmoryExporter:
break
t1map = 1 if t0map == 0 else 0
# Alloc data
t0data = [0] * num_verts * 2
t0data = np.empty([num_verts * 2], dtype=np.int16)
if has_tex1:
t1data = [0] * num_verts * 2
t1data = np.empty([num_verts * 2], dtype=np.int16)
if has_col:
cdata = [0] * num_verts * 3
cdata = np.empty([num_verts * 3], dtype=np.int16)
# va_stride = 3 + 3 # pos + nor
# va_name = 'pos_nor'
# if has_tex:
# va_stride += 2
# va_name += '_tex'
# if has_tex1:
# va_stride += 2
# va_name += '_tex1'
# if has_col > 0:
# va_stride += 3
# va_name += '_col'
# if has_tang:
# va_stride += 3
# va_name += '_tang'
# vdata = [0] * num_verts * va_stride
if has_tex:
xmax = 1.0
ymax = 1.0
for vtx in vert_list:
if abs(vtx.uvs[t0map][0]) > xmax:
xmax = abs(vtx.uvs[t0map][0])
if abs(vtx.uvs[t0map][1]) > ymax:
ymax = abs(vtx.uvs[t0map][1])
# Scale for packed coords
maxdim = max(xmax, ymax)
if maxdim > 1:
o['scale_tex'] = maxdim
invscale = 1 / o['scale_tex']
else:
invscale = 1
# TODO: handle t1map
# Make arrays
for i, vtx in enumerate(vert_list):
@ -1437,32 +1437,72 @@ class ArmoryExporter:
vdata[(i * 3) + j] = co[j]
ndata[(i * 3) + j] = normal[j]
if has_tex:
t0data[i * 2] = vtx.uvs[t0map][0]
t0data[i * 2 + 1] = 1.0 - vtx.uvs[t0map][1] # Reverse TCY
t0data[i * 2 ] = np.int16((vtx.uvs[t0map][0] * invscale) * 32767)
t0data[i * 2 + 1] = np.int16(((1.0 - vtx.uvs[t0map][1]) * invscale) * 32767) # Reverse Y
if has_tex1:
t1data[i * 2] = vtx.uvs[t1map][0]
t1data[i * 2 + 1] = 1.0 - vtx.uvs[t1map][1]
t1data[i * 2 ] = np.int16((vtx.uvs[t1map][0] * invscale) * 32767)
t1data[i * 2 + 1] = np.int16(((1.0 - vtx.uvs[t1map][1]) * invscale) * 32767)
if has_col > 0:
cdata[i * 3] = pow(vtx.col[0], 2.2)
cdata[i * 3 + 1] = pow(vtx.col[1], 2.2)
cdata[i * 3 + 2] = pow(vtx.col[2], 2.2)
cdata[i * 4 ] = np.int16(pow(vtx.col[0], 2.2) * 32767)
cdata[i * 4 + 1] = np.int16(pow(vtx.col[1], 2.2) * 32767)
cdata[i * 4 + 2] = np.int16(pow(vtx.col[2], 2.2) * 32767)
# Save aabb
aabb_min = [-0.01, -0.01, -0.01]
aabb_max = [0.01, 0.01, 0.01]
i = 0
while i < len(vdata):
if vdata[i] > aabb_max[0]:
aabb_max[0] = vdata[i]
if vdata[i + 1] > aabb_max[1]:
aabb_max[1] = vdata[i + 1]
if vdata[i + 2] > aabb_max[2]:
aabb_max[2] = vdata[i + 2]
if vdata[i] < aabb_min[0]:
aabb_min[0] = vdata[i]
if vdata[i + 1] < aabb_min[1]:
aabb_min[1] = vdata[i + 1]
if vdata[i + 2] < aabb_min[2]:
aabb_min[2] = vdata[i + 2]
i += 3
bobject.data.arm_aabb = [abs(aabb_min[0]) + abs(aabb_max[0]), abs(aabb_min[1]) + abs(aabb_max[1]), abs(aabb_min[2]) + abs(aabb_max[2])]
# Not axis-aligned
# arm_aabb = [bobject.matrix_world * Vector(v) for v in bobject.bound_box]
# Scale for packed coords
maxdim = max(bobject.data.arm_aabb[0], max(bobject.data.arm_aabb[1], bobject.data.arm_aabb[2]))
o['scale_pos'] = maxdim / 2
invscale = 1 / o['scale_pos']
# Output
o['vertex_arrays'] = []
pa = self.make_va('pos', 3, vdata)
half = np.empty([num_verts * 4], dtype=np.int16)
for i in range(num_verts):
half[i * 4 ] = np.int16((vdata[i * 3 ] * invscale) * 32767) # p.x
half[i * 4 + 1] = np.int16((vdata[i * 3 + 1] * invscale) * 32767) # p.y
half[i * 4 + 2] = np.int16((vdata[i * 3 + 2] * invscale) * 32767) # p.z
half[i * 4 + 3] = np.int16( ndata[i * 3 + 2] * 32767) # n.z
pa = self.make_va('pos', half)
o['vertex_arrays'].append(pa)
na = self.make_va('nor', 3, ndata)
half = np.empty([num_verts * 2], dtype=np.int16)
for i in range(num_verts):
half[i * 2 ] = np.int16(ndata[i * 3 ] * 32767) # n.x
half[i * 2 + 1] = np.int16(ndata[i * 3 + 1] * 32767) # n.y
na = self.make_va('nor', half)
o['vertex_arrays'].append(na)
if has_tex:
ta = self.make_va('tex', 2, t0data)
ta = self.make_va('tex', t0data)
o['vertex_arrays'].append(ta)
if has_tex1:
ta1 = self.make_va('tex1', 2, t1data)
ta1 = self.make_va('tex1', t1data)
o['vertex_arrays'].append(ta1)
if has_col:
ca = self.make_va('col', 3, cdata)
ca = self.make_va('col', cdata)
o['vertex_arrays'].append(ca)
# Indices
@ -1557,7 +1597,7 @@ class ArmoryExporter:
# Make tangents
if has_tang:
tanga_vals = self.calc_tangents(pa['values'], na['values'], ta['values'], o['index_arrays'])
tanga = self.make_va('tang', 3, tanga_vals)
tanga = self.make_va('tang', tanga_vals)
o['vertex_arrays'].append(tanga)
return vert_list
@ -1665,42 +1705,6 @@ class ArmoryExporter:
if armature:
self.export_skin(bobject, armature, vert_list, o)
# Save aabb
for va in o['vertex_arrays']:
if va['attrib'].startswith('pos'):
positions = va['values']
stride = 0
ar = va['attrib'].split('_')
for a in ar:
if a == 'pos' or a == 'nor' or a == 'col' or a == 'tang':
stride += 3
elif a == 'tex' or a == 'tex1':
stride += 2
elif a == 'bone' or a == 'weight':
stride += 4
aabb_min = [-0.01, -0.01, -0.01]
aabb_max = [0.01, 0.01, 0.01]
i = 0
while i < len(positions):
if positions[i] > aabb_max[0]:
aabb_max[0] = positions[i]
if positions[i + 1] > aabb_max[1]:
aabb_max[1] = positions[i + 1]
if positions[i + 2] > aabb_max[2]:
aabb_max[2] = positions[i + 2]
if positions[i] < aabb_min[0]:
aabb_min[0] = positions[i]
if positions[i + 1] < aabb_min[1]:
aabb_min[1] = positions[i + 1]
if positions[i + 2] < aabb_min[2]:
aabb_min[2] = positions[i + 2]
i += stride
if hasattr(bobject.data, 'arm_aabb'):
bobject.data.arm_aabb = [abs(aabb_min[0]) + abs(aabb_max[0]), abs(aabb_min[1]) + abs(aabb_max[1]), abs(aabb_min[2]) + abs(aabb_max[2])]
break
# Not axis-aligned
# arm_aabb = [bobject.matrix_world * Vector(v) for v in bobject.bound_box]
# Restore the morph state
if shapeKeys:
bobject.active_shape_key_index = activeShapeKeyIndex
@ -2043,7 +2047,7 @@ class ArmoryExporter:
vcol_export = False
vs_str = ''
for con in sd['contexts']:
for elem in con['vertex_structure']:
for elem in con['vertex_elements']:
if len(vs_str) > 0:
vs_str += ','
vs_str += elem['name']

View file

@ -106,19 +106,18 @@ def export_grease_pencil_frame(self, frame):
# TODO: merge into array of vertex arrays
fo['vertex_array'] = {}
fo['vertex_array']['attrib'] = 'pos'
fo['vertex_array']['size'] = 3
fo['vertex_array']['data'] = 'short4norm'
fo['vertex_array']['values'] = va
fo['col_array'] = {}
fo['col_array']['attrib'] = 'col'
fo['col_array']['size'] = 4
fo['col_array']['data'] = 'short4norm'
fo['col_array']['values'] = cola
fo['colfill_array'] = {}
fo['colfill_array']['attrib'] = 'colfill'
fo['colfill_array']['size'] = 4
fo['colfill_array']['data'] = 'short4norm'
fo['colfill_array']['values'] = colfilla
fo['index_array'] = {}
fo['index_array']['material'] = 0
fo['index_array']['size'] = 3
fo['index_array']['values'] = indices
fo['num_stroke_points'] = num_stroke_points
fo['frame_number'] = frame.frame_number

View file

@ -22,6 +22,7 @@
#
import struct
import io
import numpy as np
def _pack_integer(obj, fp):
if obj < 0:
@ -105,6 +106,11 @@ def _pack_array(obj, fp):
fp.write(b"\xd2")
for e in obj:
fp.write(struct.pack(">i", e))
# Int16
elif len(obj) > 0 and isinstance(obj[0], np.int16):
fp.write(b"\xd1")
for e in obj:
fp.write(struct.pack(">h", e))
# Regular
else:
for e in obj:
@ -137,7 +143,7 @@ def pack(obj, fp):
_pack_string(obj, fp)
elif isinstance(obj, bytes):
_pack_binary(obj, fp)
elif isinstance(obj, list) or isinstance(obj, tuple):
elif isinstance(obj, list) or isinstance(obj, tuple) or isinstance(obj, np.ndarray):
_pack_array(obj, fp)
elif isinstance(obj, dict):
_pack_map(obj, fp)

View file

@ -8,7 +8,7 @@ def parse_context(c, sres, asset, defs, vert=None, frag=None):
con['name'] = c['name']
con['constants'] = []
con['texture_units'] = []
con['vertex_structure'] = []
con['vertex_elements'] = []
# Names
con['vertex_shader'] = c['vertex_shader'].rsplit('.', 1)[0].split('/')[-1]
@ -77,13 +77,13 @@ def parse_context(c, sres, asset, defs, vert=None, frag=None):
def parse_shader(sres, c, con, defs, lines, parse_attributes):
skip_till_endif = 0
skip_else = False
vertex_structure_parsed = False
vertex_structure_parsing = False
vertex_elements_parsed = False
vertex_elements_parsing = False
stack = []
if parse_attributes == False:
vertex_structure_parsed = True
vertex_elements_parsed = True
for line in lines:
line = line.lstrip()
@ -116,15 +116,15 @@ def parse_shader(sres, c, con, defs, lines, parse_attributes):
if skip:
continue
if vertex_structure_parsed == False and line.startswith('in '):
vertex_structure_parsing = True
if vertex_elements_parsed == False and line.startswith('in '):
vertex_elements_parsing = True
vd = {}
s = line.split(' ')
vd['size'] = int(s[1][-1:])
vd['data'] = 'float' + s[1][-1:]
vd['name'] = s[2][:-1]
con['vertex_structure'].append(vd)
if vertex_structure_parsing == True and len(line) > 0 and line.startswith('//') == False and line.startswith('in ') == False:
vertex_structure_parsed = True
con['vertex_elements'].append(vd)
if vertex_elements_parsing == True and len(line) > 0 and line.startswith('//') == False and line.startswith('in ') == False:
vertex_elements_parsed = True
if line.startswith('uniform ') or line.startswith('//!uniform'): # Uniforms included from header files
s = line.split(' ')

View file

@ -370,10 +370,10 @@ def parse_vector(node, socket):
elif node.type == 'ATTRIBUTE':
if socket == node.outputs[0]: # Color
con.add_elem('col', 3) # Vcols only for now
con.add_elem('col', 'short4norm') # Vcols only for now
return 'vcolor'
else: # Vector
con.add_elem('tex', 2) # UVMaps only for now
con.add_elem('tex', 'short2norm') # UVMaps only for now
mat = mat_get_material()
mat_users = mat_get_material_users()
if mat_users != None and mat in mat_users:
@ -382,7 +382,7 @@ def parse_vector(node, socket):
lays = mat_user.data.uv_layers
# Second uvmap referenced
if len(lays) > 1 and node.attribute_name == lays[1].name:
con.add_elem('tex1', 2)
con.add_elem('tex1', 'short2norm')
return 'vec3(texCoord1.x, 1.0 - texCoord1.y, 0.0)'
return 'vec3(texCoord.x, 1.0 - texCoord.y, 0.0)'
@ -755,7 +755,7 @@ def parse_vector(node, socket):
elif socket == node.outputs[1]: # Normal
return 'n'
elif socket == node.outputs[2]: # UV
con.add_elem('tex', 2)
con.add_elem('tex', 'short2norm')
return 'vec3(texCoord.x, 1.0 - texCoord.y, 0.0)'
elif socket == node.outputs[3]: # Object
return 'mposition'
@ -768,7 +768,7 @@ def parse_vector(node, socket):
elif node.type == 'UVMAP':
#dupli = node.from_dupli
con.add_elem('tex', 2)
con.add_elem('tex', 'short2norm')
mat = mat_get_material()
mat_users = mat_get_material_users()
if mat_users != None and mat in mat_users:
@ -777,7 +777,7 @@ def parse_vector(node, socket):
lays = mat_user.data.uv_layers
# Second uvmap referenced
if len(lays) > 1 and node.uv_map == lays[1].name:
con.add_elem('tex1', 2)
con.add_elem('tex1', 'short2norm')
return 'vec3(texCoord1.x, 1.0 - texCoord1.y, 0.0)'
return 'vec3(texCoord.x, 1.0 - texCoord.y, 0.0)'
@ -908,7 +908,7 @@ def parse_normal_map_color_input(inp, strength_input=None):
if strength != '1.0':
frag.write('n.xy *= {0};'.format(strength))
frag.write('n = normalize(TBN * n);')
con.add_elem('tang', 3)
con.add_elem('tang', 'short4norm')
frag.write_normal -= 1
def parse_value_input(inp):
@ -1388,7 +1388,7 @@ def texture_store(node, tex, tex_name, to_linear=False, tex_link=None):
return tex_store
parsed[tex_store] = True
mat_bind_texture(tex)
con.add_elem('tex', 2)
con.add_elem('tex', 'short2norm')
curshader.add_uniform('sampler2D {0}'.format(tex_name), link=tex_link)
if node.inputs[0].is_linked:
uv_name = parse_vector_input(node.inputs[0])

View file

@ -31,15 +31,15 @@ def parse(material, mat_data, mat_users, mat_armusers):
sd = {}
sd['contexts'] = []
con = {}
con['vertex_structure'] = []
con['vertex_elements'] = []
elem = {}
elem['name'] = 'pos'
elem['size'] = 3
con['vertex_structure'].append(elem)
elem['data'] = 'short4norm'
con['vertex_elements'].append(elem)
elem = {}
elem['name'] = 'nor'
elem['size'] = 3
con['vertex_structure'].append(elem)
elem['data'] = 'short2norm'
con['vertex_elements'].append(elem)
sd['contexts'].append(con)
shader_data_name = material.arm_custom_material
bind_constants = {}

View file

@ -0,0 +1,48 @@
import arm.material.mat_state as mat_state
import arm.material.make_skin as make_skin
import arm.material.make_particle as make_particle
import arm.material.make_inst as make_inst
import arm.utils
import arm.material.cycles as cycles
def write_vertpos(vert):
billboard = mat_state.material.arm_billboard
particle = mat_state.material.arm_particle_flag
# Particles
if particle:
if arm.utils.get_rp().arm_particles == 'GPU':
make_particle.write(vert, particle_info=cycles.particle_info)
# Billboards
if billboard == 'spherical':
vert.add_uniform('mat4 WV', '_worldViewMatrix')
vert.add_uniform('mat4 P', '_projectionMatrix')
vert.write('gl_Position = P * (WV * vec4(0.0, 0.0, spos.z, 1.0) + vec4(spos.x, spos.y, 0.0, 0.0));')
else:
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
vert.write('gl_Position = WVP * spos;')
else:
# Billboards
if billboard == 'spherical':
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixSphere')
elif billboard == 'cylindrical':
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixCylinder')
else: # off
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
vert.write('gl_Position = WVP * spos;')
def write_norpos(con_mesh, vert, declare=False, write_nor=True):
prep = ''
if declare:
prep = 'vec3 '
vert.write_pre = True
is_bone = con_mesh.is_elem('bone')
if is_bone:
make_skin.skin_pos(vert)
if write_nor:
if is_bone:
make_skin.skin_nor(vert, prep)
else:
vert.write(prep + 'wnormal = normalize(N * vec3(nor.xy, pos.w));')
if con_mesh.is_elem('ipos'):
make_inst.inst_pos(con_mesh, vert)
vert.write_pre = False

View file

@ -1,7 +1,7 @@
import arm.material.cycles as cycles
import arm.material.mat_state as mat_state
import arm.material.mat_utils as mat_utils
import arm.material.make_mesh as make_mesh
import arm.material.make_finalize as make_finalize
import arm.utils
def make(context_id):
@ -25,7 +25,7 @@ def make(context_id):
vert.add_out('vec3 wnormal')
vert.write('wnormal = N * vec3(0.0, 0.0, 1.0);')
vert.write('wvpposition = WVP * vec4(pos, 1.0);')
vert.write('wvpposition = WVP * vec4(pos.xyz, 1.0);')
vert.write('gl_Position = wvpposition;')
frag.add_include('compiled.inc')
@ -65,6 +65,6 @@ def make(context_id):
frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), opacity);')
frag.write('fragColor[1] = vec4(basecol.rgb, opacity);')
make_mesh.make_finalize(con_decal)
make_finalize.make(con_decal)
return con_decal

View file

@ -6,7 +6,7 @@ import arm.material.make_skin as make_skin
import arm.material.make_inst as make_inst
import arm.material.make_tess as make_tess
import arm.material.make_particle as make_particle
import arm.material.make_mesh as make_mesh
import arm.material.make_finalize as make_finalize
import arm.assets as assets
import arm.utils
@ -14,9 +14,9 @@ def make(context_id, rpasses, shadowmap=False):
is_disp = mat_utils.disp_linked(mat_state.output_node)
vs = [{'name': 'pos', 'size': 3}]
vs = [{'name': 'pos', 'data': 'short4norm'}]
if is_disp:
vs.append({'name': 'nor', 'size': 3})
vs.append({'name': 'nor', 'data': 'short2norm'})
con_depth = mat_state.data.add_context({ 'name': context_id, 'vertex_structure': vs, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False })
@ -26,7 +26,7 @@ def make(context_id, rpasses, shadowmap=False):
tesc = None
tese = None
vert.write_attrib('vec4 spos = vec4(pos, 1.0);')
vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);')
parse_opacity = 'translucent' in rpasses or mat_state.material.arm_discard
if parse_opacity:
@ -51,10 +51,12 @@ def make(context_id, rpasses, shadowmap=False):
cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity)
if con_depth.is_elem('tex'):
vert.add_out('vec2 texCoord') ## vs only, remove out
vert.write_attrib('texCoord = tex;')
vert.add_uniform('float texUnpack', link='_texUnpack')
vert.write_attrib('texCoord = tex * texUnpack;')
if con_depth.is_elem('tex1'):
vert.add_out('vec2 texCoord1') ## vs only, remove out
vert.write_attrib('texCoord1 = tex1;')
vert.add_uniform('float texUnpack', link='_texUnpack')
vert.write_attrib('texCoord1 = tex1 * texUnpack;')
if con_depth.is_elem('col'):
vert.add_out('vec3 vcolor')
vert.write_attrib('vcolor = col;')
@ -75,7 +77,7 @@ def make(context_id, rpasses, shadowmap=False):
vert.add_out('vec3 wnormal')
vert.add_uniform('mat3 N', '_normalMatrix')
vert.write('wnormal = normalize(N * nor);')
vert.write('wnormal = normalize(N * vec3(nor.xy, pos.w));')
make_tess.tesc_levels(tesc, rpdat.arm_tess_shadows_inner, rpdat.arm_tess_shadows_outer)
make_tess.interpolate(tese, 'wposition', 3)
@ -85,7 +87,8 @@ def make(context_id, rpasses, shadowmap=False):
if con_depth.is_elem('tex'):
vert.add_out('vec2 texCoord')
vert.write('texCoord = tex;')
vert.add_uniform('float texUnpack', link='_texUnpack')
vert.write('texCoord = tex * texUnpack;')
tese.write_pre = True
make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord'))
tese.write_pre = False
@ -138,11 +141,12 @@ def make(context_id, rpasses, shadowmap=False):
if con_depth.is_elem('tex'):
vert.add_out('vec2 texCoord')
vert.add_uniform('float texUnpack', link='_texUnpack')
if mat_state.material.arm_tilesheet_mat:
vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset')
vert.write('texCoord = tex + tilesheetOffset;')
vert.write('texCoord = tex * texUnpack + tilesheetOffset;')
else:
vert.write('texCoord = tex;')
vert.write('texCoord = tex * texUnpack;')
if con_depth.is_elem('tex1'):
vert.add_out('vec2 texCoord1')
@ -156,7 +160,7 @@ def make(context_id, rpasses, shadowmap=False):
opac = mat_state.material.arm_discard_opacity_shadows
frag.write('if (opacity < {0}) discard;'.format(opac))
make_mesh.make_finalize(con_depth)
make_finalize.make(con_depth)
assets.vs_equal(con_depth, assets.shader_cons['depth_vert'])
assets.fs_equal(con_depth, assets.shader_cons['depth_frag'])

View file

@ -0,0 +1,103 @@
def make(con_mesh):
vert = con_mesh.vert
frag = con_mesh.frag
geom = con_mesh.geom
tesc = con_mesh.tesc
tese = con_mesh.tese
# Additional values referenced in cycles
# TODO: enable from cycles.py
if frag.contains('dotNV') and not frag.contains('float dotNV'):
frag.write_init('float dotNV = max(dot(n, vVec), 0.0);')
write_wpos = False
if frag.contains('vVec') and not frag.contains('vec3 vVec'):
if tese != None:
tese.add_out('vec3 eyeDir')
tese.add_uniform('vec3 eye', '_cameraPosition')
tese.write('eyeDir = eye - wposition;')
else:
if not vert.contains('wposition'):
write_wpos = True
vert.add_out('vec3 eyeDir')
vert.add_uniform('vec3 eye', '_cameraPosition')
vert.write('eyeDir = eye - wposition;')
frag.write_attrib('vec3 vVec = normalize(eyeDir);')
export_wpos = False
if frag.contains('wposition') and not frag.contains('vec3 wposition'):
export_wpos = True
if tese != None:
export_wpos = True
if vert.contains('wposition'):
write_wpos = True
if export_wpos:
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_out('vec3 wposition')
vert.write_attrib('wposition = vec4(W * spos).xyz;')
elif write_wpos:
vert.add_uniform('mat4 W', '_worldMatrix')
vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;')
frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition')
if frag_mpos:
vert.add_out('vec3 mposition')
vert.write_attrib('mposition = spos.xyz;')
if tese != None:
if frag_mpos:
make_tess.interpolate(tese, 'mposition', 3, declare_out=True)
elif tese.contains('mposition') and not tese.contains('vec3 mposition'):
vert.add_out('vec3 mposition')
vert.write_pre = True
vert.write('mposition = spos.xyz;')
vert.write_pre = False
make_tess.interpolate(tese, 'mposition', 3, declare_out=False)
frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition')
if frag_bpos:
vert.add_out('vec3 bposition')
vert.add_uniform('vec3 dim', link='_dim')
vert.add_uniform('vec3 hdim', link='_halfDim')
vert.write_pre = True
vert.write('bposition = (spos.xyz + hdim) / dim;')
vert.write_pre = False
if tese != None:
if frag_bpos:
make_tess.interpolate(tese, 'bposition', 3, declare_out=True)
elif tese.contains('bposition') and not tese.contains('vec3 bposition'):
vert.add_out('vec3 bposition')
vert.write_pre = True
vert.write('bposition = spos.xyz;')
vert.write_pre = False
make_tess.interpolate(tese, 'bposition', 3, declare_out=False)
frag_wtan = (frag.contains('wtangent') and not frag.contains('vec3 wtangent')) or vert.contains('wtangent')
if frag_wtan:
# Indicate we want tang attrib in finalizer to prevent TBN generation
con_mesh.add_elem('tex', 'short2norm')
con_mesh.add_elem('tang', 'short4norm')
vert.add_out('vec3 wtangent')
vert.write_pre = True
vert.write('wtangent = normalize(N * tang.xyz);')
vert.write_pre = False
if tese != None:
if frag_wtan:
make_tess.interpolate(tese, 'wtangent', 3, declare_out=True)
elif tese.contains('wtangent') and not tese.contains('vec3 wtangent'):
vert.add_out('vec3 wtangent')
vert.write_pre = True
vert.write('wtangent = normalize(N * tang.xyz);')
vert.write_pre = False
make_tess.interpolate(tese, 'wtangent', 3, declare_out=False)
if frag.contains('vVecCam'):
vert.add_out('vec3 eyeDirCam')
vert.add_uniform('mat4 WV', '_worldViewMatrix')
vert.write('eyeDirCam = vec4(WV * spos).xyz; eyeDirCam.z *= -1;')
frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);')

View file

@ -3,11 +3,11 @@ import arm.assets as assets
import arm.material.mat_state as mat_state
import arm.material.mat_utils as mat_utils
import arm.material.cycles as cycles
import arm.material.make_skin as make_skin
import arm.material.make_inst as make_inst
import arm.material.make_tess as make_tess
import arm.material.make_particle as make_particle
import arm.material.make_cluster as make_cluster
import arm.material.make_finalize as make_finalize
import arm.material.make_attrib as make_attrib
import arm.utils
is_displacement = False
@ -57,115 +57,12 @@ def make(context_id):
elif rid == 'Raytracer':
make_raytracer(con_mesh)
make_finalize(con_mesh)
make_finalize.make(con_mesh)
assets.vs_equal(con_mesh, assets.shader_cons['mesh_vert'])
return con_mesh
def make_finalize(con_mesh):
vert = con_mesh.vert
frag = con_mesh.frag
geom = con_mesh.geom
tesc = con_mesh.tesc
tese = con_mesh.tese
# Additional values referenced in cycles
# TODO: enable from cycles.py
if frag.contains('dotNV') and not frag.contains('float dotNV'):
frag.write_init('float dotNV = max(dot(n, vVec), 0.0);')
write_wpos = False
if frag.contains('vVec') and not frag.contains('vec3 vVec'):
if tese != None:
tese.add_out('vec3 eyeDir')
tese.add_uniform('vec3 eye', '_cameraPosition')
tese.write('eyeDir = eye - wposition;')
else:
if not vert.contains('wposition'):
write_wpos = True
vert.add_out('vec3 eyeDir')
vert.add_uniform('vec3 eye', '_cameraPosition')
vert.write('eyeDir = eye - wposition;')
frag.write_attrib('vec3 vVec = normalize(eyeDir);')
export_wpos = False
if frag.contains('wposition') and not frag.contains('vec3 wposition'):
export_wpos = True
if tese != None:
export_wpos = True
if vert.contains('wposition'):
write_wpos = True
if export_wpos:
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_out('vec3 wposition')
vert.write_attrib('wposition = vec4(W * spos).xyz;')
elif write_wpos:
vert.add_uniform('mat4 W', '_worldMatrix')
vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;')
frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition')
if frag_mpos:
vert.add_out('vec3 mposition')
vert.write_attrib('mposition = spos.xyz;')
if tese != None:
if frag_mpos:
make_tess.interpolate(tese, 'mposition', 3, declare_out=True)
elif tese.contains('mposition') and not tese.contains('vec3 mposition'):
vert.add_out('vec3 mposition')
vert.write_pre = True
vert.write('mposition = spos.xyz;')
vert.write_pre = False
make_tess.interpolate(tese, 'mposition', 3, declare_out=False)
frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition')
if frag_bpos:
vert.add_out('vec3 bposition')
vert.add_uniform('vec3 dim', link='_dim')
vert.add_uniform('vec3 hdim', link='_halfDim')
vert.write_pre = True
vert.write('bposition = (spos.xyz + hdim) / dim;')
vert.write_pre = False
if tese != None:
if frag_bpos:
make_tess.interpolate(tese, 'bposition', 3, declare_out=True)
elif tese.contains('bposition') and not tese.contains('vec3 bposition'):
vert.add_out('vec3 bposition')
vert.write_pre = True
vert.write('bposition = spos.xyz;')
vert.write_pre = False
make_tess.interpolate(tese, 'bposition', 3, declare_out=False)
frag_wtan = (frag.contains('wtangent') and not frag.contains('vec3 wtangent')) or vert.contains('wtangent')
if frag_wtan:
# Indicate we want tang attrib in finalizer to prevent TBN generation
con_mesh.add_elem('tex', 2)
con_mesh.add_elem('tang', 3)
vert.add_out('vec3 wtangent')
vert.write_pre = True
vert.write('wtangent = normalize(N * tang);')
vert.write_pre = False
if tese != None:
if frag_wtan:
make_tess.interpolate(tese, 'wtangent', 3, declare_out=True)
elif tese.contains('wtangent') and not tese.contains('vec3 wtangent'):
vert.add_out('vec3 wtangent')
vert.write_pre = True
vert.write('wtangent = normalize(N * tang);')
vert.write_pre = False
make_tess.interpolate(tese, 'wtangent', 3, declare_out=False)
if frag.contains('vVecCam'):
vert.add_out('vec3 eyeDirCam')
vert.add_uniform('mat4 WV', '_worldViewMatrix')
vert.write('eyeDirCam = vec4(WV * spos).xyz; eyeDirCam.z *= -1;')
frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);')
def make_base(con_mesh, parse_opacity):
global is_displacement
global write_material_attribs
@ -179,7 +76,7 @@ def make_base(con_mesh, parse_opacity):
tese = None
vert.add_uniform('mat3 N', '_normalMatrix')
vert.write_attrib('vec4 spos = vec4(pos, 1.0);')
vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);')
vattr_written = False
rpdat = arm.utils.get_rp()
@ -220,18 +117,19 @@ def make_base(con_mesh, parse_opacity):
write_material_attribs_post(con_mesh, frag)
if not is_displacement and not vattr_written:
write_vertpos(vert)
make_attrib.write_vertpos(vert)
if con_mesh.is_elem('tex'):
vert.add_out('vec2 texCoord')
vert.add_uniform('float texUnpack', link='_texUnpack')
if mat_state.material.arm_tilesheet_mat:
if mat_state.material.arm_particle_flag and rpdat.arm_particles == 'GPU':
make_particle.write_tilesheet(vert)
else:
vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset')
vert.write_attrib('texCoord = tex + tilesheetOffset;')
vert.write_attrib('texCoord = tex * texUnpack + tilesheetOffset;')
else:
vert.write_attrib('texCoord = tex;')
vert.write_attrib('texCoord = tex * texUnpack;')
if tese != None:
tese.write_pre = True
@ -240,7 +138,8 @@ def make_base(con_mesh, parse_opacity):
if con_mesh.is_elem('tex1'):
vert.add_out('vec2 texCoord1')
vert.write_attrib('texCoord1 = tex1;')
vert.add_uniform('float texUnpack', link='_texUnpack')
vert.write_attrib('texCoord1 = tex1 * texUnpack;')
if tese != None:
tese.write_pre = True
make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1'))
@ -257,19 +156,19 @@ def make_base(con_mesh, parse_opacity):
if con_mesh.is_elem('tang'):
if tese != None:
vert.add_out('vec3 wnormal')
write_norpos(con_mesh, vert)
make_attrib.write_norpos(con_mesh, vert)
tese.add_out('mat3 TBN')
tese.write('vec3 wbitangent = normalize(cross(wnormal, wtangent));')
tese.write('TBN = mat3(wtangent, wbitangent, wnormal);')
else:
vert.add_out('mat3 TBN')
write_norpos(con_mesh, vert, declare=True)
vert.write('vec3 tangent = normalize(N * tang);')
make_attrib.write_norpos(con_mesh, vert, declare=True)
vert.write('vec3 tangent = normalize(N * tang.xyz);')
vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));')
vert.write('TBN = mat3(tangent, bitangent, wnormal);')
else:
vert.add_out('vec3 wnormal')
write_norpos(con_mesh, vert)
make_attrib.write_norpos(con_mesh, vert)
frag.write_attrib('vec3 n = normalize(wnormal);')
if is_displacement:
@ -281,48 +180,6 @@ def make_base(con_mesh, parse_opacity):
sh.write('wposition += wnormal * disp * 0.1;')
sh.write('gl_Position = VP * vec4(wposition, 1.0);')
def write_vertpos(vert):
billboard = mat_state.material.arm_billboard
particle = mat_state.material.arm_particle_flag
# Particles
if particle:
if arm.utils.get_rp().arm_particles == 'GPU':
make_particle.write(vert, particle_info=cycles.particle_info)
# Billboards
if billboard == 'spherical':
vert.add_uniform('mat4 WV', '_worldViewMatrix')
vert.add_uniform('mat4 P', '_projectionMatrix')
vert.write('gl_Position = P * (WV * vec4(0.0, 0.0, spos.z, 1.0) + vec4(spos.x, spos.y, 0.0, 0.0));')
else:
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
vert.write('gl_Position = WVP * spos;')
else:
# Billboards
if billboard == 'spherical':
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixSphere')
elif billboard == 'cylindrical':
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixCylinder')
else: # off
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
vert.write('gl_Position = WVP * spos;')
def write_norpos(con_mesh, vert, declare=False, write_nor=True):
prep = ''
if declare:
prep = 'vec3 '
vert.write_pre = True
is_bone = con_mesh.is_elem('bone')
if is_bone:
make_skin.skin_pos(vert)
if write_nor:
if is_bone:
make_skin.skin_nor(vert, prep)
else:
vert.write(prep + 'wnormal = normalize(N * nor);')
if con_mesh.is_elem('ipos'):
make_inst.inst_pos(con_mesh, vert)
vert.write_pre = False
def make_deferred(con_mesh):
wrd = bpy.data.worlds['Arm']
rpdat = arm.utils.get_rp()
@ -405,7 +262,7 @@ def make_raytracer(con_mesh):
frag = con_mesh.make_frag()
vert.add_out('vec3 n')
vert.write('n = nor;')
vert.write('gl_Position = vec4(pos, 1.0);')
vert.write('gl_Position = vec4(pos.xyz, 1.0);')
def make_forward_mobile(con_mesh):
wrd = bpy.data.worlds['Arm']
@ -416,10 +273,10 @@ def make_forward_mobile(con_mesh):
tese = None
vert.add_uniform('mat3 N', '_normalMatrix')
vert.write_attrib('vec4 spos = vec4(pos, 1.0);')
vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);')
frag.ins = vert.outs
write_vertpos(vert)
make_attrib.write_vertpos(vert)
frag.add_include('compiled.inc')
frag.write('vec3 basecol;')
@ -443,11 +300,12 @@ def make_forward_mobile(con_mesh):
if con_mesh.is_elem('tex'):
vert.add_out('vec2 texCoord')
vert.add_uniform('float texUnpack', link='_texUnpack')
if mat_state.material.arm_tilesheet_mat:
vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset')
vert.write('texCoord = tex + tilesheetOffset;')
vert.write('texCoord = tex * texUnpack + tilesheetOffset;')
else:
vert.write('texCoord = tex;')
vert.write('texCoord = tex * texUnpack;')
if con_mesh.is_elem('col'):
vert.add_out('vec3 vcolor')
@ -455,13 +313,13 @@ def make_forward_mobile(con_mesh):
if con_mesh.is_elem('tang'):
vert.add_out('mat3 TBN')
write_norpos(con_mesh, vert, declare=True)
make_attrib.write_norpos(con_mesh, vert, declare=True)
vert.write('vec3 tangent = normalize(N * tang);')
vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));')
vert.write('TBN = mat3(tangent, bitangent, wnormal);')
else:
vert.add_out('vec3 wnormal')
write_norpos(con_mesh, vert)
make_attrib.write_norpos(con_mesh, vert)
frag.write_attrib('vec3 n = normalize(wnormal);')
frag.add_include('std/math.glsl')
@ -564,15 +422,15 @@ def make_forward_solid(con_mesh):
tesc = None
tese = None
for e in con_mesh.data['vertex_structure']:
for e in con_mesh.data['vertex_elements']:
if e['name'] == 'nor':
con_mesh.data['vertex_structure'].remove(e)
con_mesh.data['vertex_elements'].remove(e)
break
vert.write_attrib('vec4 spos = vec4(pos, 1.0);')
vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);')
frag.ins = vert.outs
write_vertpos(vert)
make_attrib.write_vertpos(vert)
frag.add_include('compiled.inc')
frag.write('vec3 basecol;')
@ -596,17 +454,18 @@ def make_forward_solid(con_mesh):
if con_mesh.is_elem('tex'):
vert.add_out('vec2 texCoord')
vert.add_uniform('float texUnpack', link='_texUnpack')
if mat_state.material.arm_tilesheet_mat:
vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset')
vert.write('texCoord = tex + tilesheetOffset;')
vert.write('texCoord = tex * texUnpack + tilesheetOffset;')
else:
vert.write('texCoord = tex;')
vert.write('texCoord = tex * texUnpack;')
if con_mesh.is_elem('col'):
vert.add_out('vec3 vcolor')
vert.write('vcolor = col;')
write_norpos(con_mesh, vert, write_nor=False)
make_attrib.write_norpos(con_mesh, vert, write_nor=False)
frag.add_out('vec4 fragColor')
if blend and parse_opacity:

View file

@ -95,5 +95,5 @@ def write_tilesheet(vert):
vert.write('int tx = frame % int(pd[3][0]);')
vert.write('int ty = int(frame / pd[3][0]);')
vert.write('vec2 tilesheetOffset = vec2(tx * (1 / pd[3][0]), ty * (1 / pd[3][1]));')
vert.write('texCoord = tex + tilesheetOffset;')
vert.write('texCoord = tex * texUnpack + tilesheetOffset;')
# vert.write('texCoord = tex;')

View file

@ -42,15 +42,15 @@ def build(material, mat_users, mat_armusers):
for bo in mat_users[material]:
# GPU Skinning
if arm.utils.export_bone_data(bo):
global_elems.append({'name': 'bone', 'size': 4})
global_elems.append({'name': 'weight', 'size': 4})
global_elems.append({'name': 'bone', 'data': 'short4norm'})
global_elems.append({'name': 'weight', 'data': 'short4norm'})
# Instancing
if bo.arm_instanced != 'Off' or material.arm_particle_flag:
global_elems.append({'name': 'ipos', 'size': 3})
global_elems.append({'name': 'ipos', 'data': 'float3'})
if bo.arm_instanced == 'Loc + Rot' or bo.arm_instanced == 'Loc + Rot + Scale':
global_elems.append({'name': 'irot', 'size': 3})
global_elems.append({'name': 'irot', 'data': 'float3'})
if bo.arm_instanced == 'Loc + Scale' or bo.arm_instanced == 'Loc + Rot + Scale':
global_elems.append({'name': 'iscl', 'size': 3})
global_elems.append({'name': 'iscl', 'data': 'float3'})
mat_state.data.global_elems = global_elems

View file

@ -24,7 +24,7 @@ def skin_nor(vert, prep):
rpdat = arm.utils.get_rp()
if rpdat.arm_skin == 'GPU (Matrix)':
vert.write('mat3 skinningMatVec = getSkinningMatVec(skinningMat);')
vert.write(prep + 'wnormal = normalize(N * (nor * skinningMatVec));')
vert.write(prep + 'wnormal = normalize(N * (vec3(nor.xy, pos.w) * skinningMatVec));')
else: # Dual Quat
vert.write(prep + 'wnormal = normalize(N * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));')
vert.write(prep + 'wnormal = normalize(N * (vec3(nor.xy, pos.w) + 2.0 * cross(skinA.xyz, cross(skinA.xyz, vec3(nor.xy, pos.w)) + skinA.w * vec3(nor.xy, pos.w))));')

View file

@ -1,6 +1,7 @@
import arm.material.cycles as cycles
import arm.material.mat_state as mat_state
import arm.material.make_mesh as make_mesh
import arm.material.make_finalize as make_finalize
import arm.assets as assets
def make(context_id):
@ -31,7 +32,7 @@ def make(context_id):
frag.write('fragColor[0] = vec4(premultipliedReflect.rgb * w, premultipliedReflect.a);')
frag.write('fragColor[1] = vec4(premultipliedReflect.a * w, 0.0, 0.0, 1.0);')
make_mesh.make_finalize(con_transluc)
make_finalize.make(con_transluc)
# assets.vs_equal(con_transluc, assets.shader_cons['transluc_vert']) # shader_cons has no transluc yet
# assets.fs_equal(con_transluc, assets.shader_cons['transluc_frag'])

View file

@ -109,10 +109,10 @@ def make_gi(context_id):
if rpdat.arm_voxelgi_revoxelize and rpdat.arm_voxelgi_camera:
vert.add_uniform('vec3 eyeSnap', '_cameraPositionSnap')
vert.write('voxpositionGeom = (vec3(W * vec4(pos, 1.0)) - eyeSnap) / voxelgiHalfExtents;')
vert.write('voxpositionGeom = (vec3(W * vec4(pos.xyz, 1.0)) - eyeSnap) / voxelgiHalfExtents;')
else:
vert.write('voxpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiHalfExtents;')
vert.write('wnormalGeom = normalize(N * nor);')
vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0)) / voxelgiHalfExtents;')
vert.write('wnormalGeom = normalize(N * vec3(nor.xy, pos.w));')
# vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);')
geom.add_out('vec3 voxposition')
@ -213,9 +213,9 @@ def make_ao(context_id):
if arm.utils.get_gapi() == 'direct3d11':
for e in con_voxel.data['vertex_structure']:
for e in con_voxel.data['vertex_elements']:
if e['name'] == 'nor':
con_voxel.data['vertex_structure'].remove(e)
con_voxel.data['vertex_elements'].remove(e)
break
# No geom shader compiler for hlsl yet
@ -225,7 +225,7 @@ def make_ao(context_id):
vert.add_uniform('mat4 W', '_worldMatrix')
vert.write('uniform float4x4 W;')
vert.write('struct SPIRV_Cross_Input { float3 pos : TEXCOORD0; };')
vert.write('struct SPIRV_Cross_Input { float4 pos : TEXCOORD0; };')
vert.write('struct SPIRV_Cross_Output { float4 svpos : SV_POSITION; };')
vert.write('SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) {')
vert.write(' SPIRV_Cross_Output stage_output;')
@ -292,9 +292,9 @@ def make_ao(context_id):
if rpdat.arm_voxelgi_revoxelize and rpdat.arm_voxelgi_camera:
vert.add_uniform('vec3 eyeSnap', '_cameraPositionSnap')
vert.write('voxpositionGeom = (vec3(W * vec4(pos, 1.0)) - eyeSnap) / voxelgiHalfExtents;')
vert.write('voxpositionGeom = (vec3(W * vec4(pos.xyz, 1.0)) - eyeSnap) / voxelgiHalfExtents;')
else:
vert.write('voxpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiHalfExtents;')
vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0)) / voxelgiHalfExtents;')
# vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);')

View file

@ -18,7 +18,7 @@ class ShaderData:
con = ShaderContext(self.material, self.sd, props)
if con not in self.sd['contexts']:
for elem in self.global_elems:
con.add_elem(elem['name'], elem['size'])
con.add_elem(elem['name'], elem['data'])
self.sd['contexts'].append(con.get())
return con
@ -41,10 +41,10 @@ class ShaderContext:
self.data['depth_write'] = props['depth_write']
self.data['compare_mode'] = props['compare_mode']
self.data['cull_mode'] = props['cull_mode']
if 'vertex_structure' in props:
self.data['vertex_structure'] = props['vertex_structure']
if 'vertex_elements' in props:
self.data['vertex_elements'] = props['vertex_elements']
else:
self.data['vertex_structure'] = [{'name': 'pos', 'size': 3}, {'name': 'nor', 'size': 3}]
self.data['vertex_elements'] = [{'name': 'pos', 'data': 'short4norm'}, {'name': 'nor', 'data': 'short2norm'}] # (p.xyz, n.z), (n.xy)
if 'blend_source' in props:
self.data['blend_source'] = props['blend_source']
if 'blend_destination' in props:
@ -79,10 +79,10 @@ class ShaderContext:
self.data['constants'] = []
self.constants = self.data['constants']
def add_elem(self, name, size):
elem = { 'name': name, 'size': size }
if elem not in self.data['vertex_structure']:
self.data['vertex_structure'].append(elem)
def add_elem(self, name, data):
elem = { 'name': name, 'data': data }
if elem not in self.data['vertex_elements']:
self.data['vertex_elements'].append(elem)
self.sort_vs()
def sort_vs(self):
@ -93,16 +93,16 @@ class ShaderContext:
elem = self.get_elem(ename)
if elem != None:
vs.append(elem)
self.data['vertex_structure'] = vs
self.data['vertex_elements'] = vs
def is_elem(self, name):
for elem in self.data['vertex_structure']:
for elem in self.data['vertex_elements']:
if elem['name'] == name:
return True
return False
def get_elem(self, name):
for elem in self.data['vertex_structure']:
for elem in self.data['vertex_elements']:
if elem['name'] == name:
return elem
return None
@ -262,12 +262,26 @@ class Shader:
self.main_textures == sh.main_textures and \
self.main_attribs == sh.main_attribs
def data_size(self, data):
if data == 'float1':
return '1'
elif data == 'float2':
return '2'
elif data == 'float3':
return '3'
elif data == 'float4':
return '4'
elif data == 'short2norm':
return '2'
elif data == 'short4norm':
return '4'
def vstruct_to_vsin(self):
if self.shader_type != 'vert' or self.ins != [] or not self.vstruct_as_vsin: # Vertex structure as vertex shader input
return
vs = self.context.data['vertex_structure']
vs = self.context.data['vertex_elements']
for e in vs:
self.add_in('vec' + str(e['size']) + ' ' + e['name'])
self.add_in('vec' + self.data_size(e['data']) + ' ' + e['name'])
def get(self):
if self.noprocessing:

View file

@ -199,9 +199,11 @@ def init_properties():
bpy.types.Mesh.arm_dynamic_usage = BoolProperty(name="Dynamic Usage", description="Mesh data can change at runtime", default=False)
bpy.types.Mesh.arm_compress = BoolProperty(name="Compress", description="Pack data into zip file", default=False)
bpy.types.Curve.arm_cached = BoolProperty(name="Mesh Cached", description="No need to reexport curve data", default=False)
bpy.types.Curve.arm_aabb = FloatVectorProperty(name="AABB", size=3, default=[0,0,0])
bpy.types.Curve.arm_compress = BoolProperty(name="Compress", description="Pack data into zip file", default=False)
bpy.types.Curve.arm_dynamic_usage = BoolProperty(name="Dynamic Data Usage", description="Curve data can change at runtime", default=False)
bpy.types.MetaBall.arm_cached = BoolProperty(name="Mesh Cached", description="No need to reexport metaball data", default=False)
bpy.types.MetaBall.arm_aabb = FloatVectorProperty(name="AABB", size=3, default=[0,0,0])
bpy.types.MetaBall.arm_compress = BoolProperty(name="Compress", description="Pack data into zip file", default=False)
bpy.types.MetaBall.arm_dynamic_usage = BoolProperty(name="Dynamic Data Usage", description="Metaball data can change at runtime", default=False)
# For grease pencil
@ -241,7 +243,7 @@ def init_properties():
('clockwise', 'Front', 'Clockwise'),
('counter_clockwise', 'Back', 'Counter-Clockwise')],
name="", default='clockwise', description="Draw geometry faces")
bpy.types.Material.arm_discard = BoolProperty(name="Discard", default=False, description="Do not render fragments below specified opacity threshold")
bpy.types.Material.arm_discard = BoolProperty(name="Discard", default=False, description="Alpha test - do not render fragments below specified opacity threshold")
bpy.types.Material.arm_discard_opacity = FloatProperty(name="Mesh Opacity", default=0.2, min=0, max=1)
bpy.types.Material.arm_discard_opacity_shadows = FloatProperty(name="Shadows Opacity", default=0.1, min=0, max=1)
bpy.types.Material.arm_custom_material = StringProperty(name="Custom Material", description="Write custom material", default='')

View file

@ -271,8 +271,6 @@ project.addSources('Sources');
# if bpy.data.scenes[0].unit_settings.system_rotation == 'DEGREES':
# assets.add_khafile_def('arm_degrees')
assets.add_khafile_def('arm_fast')
for d in assets.khafile_defs:
f.write("project.addDefine('" + d + "');\n")