/src/de/nulldesign/nd2d/materials/AMaterial.as
ActionScript | 267 lines | 171 code | 59 blank | 37 comment | 33 complexity | f591b52eca8fd36af3a053c2f665eee3 MD5 | raw file
- /*
- * ND2D - A Flash Molehill GPU accelerated 2D engine
- *
- * Author: Lars Gerckens
- * Copyright (c) nulldesign 2011
- * Repository URL: http://github.com/nulldesign/nd2d
- * Getting started: https://github.com/nulldesign/nd2d/wiki
- *
- *
- * Licence Agreement
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- package de.nulldesign.nd2d.materials {
- import de.nulldesign.nd2d.geom.Face;
- import de.nulldesign.nd2d.geom.UV;
- import de.nulldesign.nd2d.geom.Vertex;
- import de.nulldesign.nd2d.materials.shader.Shader2D;
- import de.nulldesign.nd2d.utils.NodeBlendMode;
- import flash.display.Shader;
- import flash.display3D.Context3D;
- import flash.display3D.Context3DVertexBufferFormat;
- import flash.display3D.IndexBuffer3D;
- import flash.display3D.VertexBuffer3D;
- import flash.geom.Matrix3D;
- import flash.utils.Dictionary;
- public class AMaterial {
- // cameras view projectionmatrix
- public var viewProjectionMatrix:Matrix3D;
- // models modelmatrix
- public var modelMatrix:Matrix3D;
- public var clipSpaceMatrix:Matrix3D = new Matrix3D();
- public var numTris:int = 0;
- public var drawCalls:int = 0;
- public var blendMode:NodeBlendMode = BlendModePresets.NORMAL_PREMULTIPLIED_ALPHA;
- public var needUploadVertexBuffer:Boolean = false;
- protected var indexBuffer:IndexBuffer3D;
- protected var vertexBuffer:VertexBuffer3D;
- protected var mIndexBuffer:Vector.<uint>;
- protected var mVertexBuffer:Vector.<Number>;
- protected var shaderData:Shader2D;
- protected var programConstVector:Vector.<Number> = new Vector.<Number>(4);
- public var nodeTinted:Boolean = false;
- protected var previousTintedState:Boolean = false;
- public static const VERTEX_POSITION:String = "PB3D_POSITION";
- public static const VERTEX_UV:String = "PB3D_UV";
- public static const VERTEX_COLOR:String = "PB3D_COLOR";
- public function AMaterial() {
- }
- protected function generateBufferData(context:Context3D, faceList:Vector.<Face>):void {
- if(vertexBuffer) {
- return;
- }
- initProgram(context);
- var i:int;
- const numFaces:int = faceList.length;
- var numIndices:int;
- mIndexBuffer = new Vector.<uint>();
- mVertexBuffer = new Vector.<Number>();
- var duplicateCheck:Dictionary = new Dictionary();
- var tmpUID:String;
- var indexBufferIdx:uint = 0;
- var face:Face;
- // generate index + vertexbuffer
- // integrated check if the vertex / uv combination is already in the buffer and skip these vertices
- for(i = 0; i < numFaces; i++) {
- face = faceList[i];
- tmpUID = face.v1.uid + "." + face.uv1.uid;
- if(duplicateCheck[tmpUID] == undefined) {
- addVertex(context, mVertexBuffer, face.v1, face.uv1, face);
- duplicateCheck[tmpUID] = indexBufferIdx;
- mIndexBuffer.push(indexBufferIdx);
- face.v1.bufferIdx = indexBufferIdx;
- ++indexBufferIdx;
- } else {
- mIndexBuffer.push(duplicateCheck[tmpUID]);
- }
- tmpUID = face.v2.uid + "." + face.uv2.uid;
- if(duplicateCheck[tmpUID] == undefined) {
- addVertex(context, mVertexBuffer, face.v2, face.uv2, face);
- duplicateCheck[tmpUID] = indexBufferIdx;
- mIndexBuffer.push(indexBufferIdx);
- face.v2.bufferIdx = indexBufferIdx;
- ++indexBufferIdx;
- } else {
- mIndexBuffer.push(duplicateCheck[tmpUID]);
- }
- tmpUID = face.v3.uid + "." + face.uv3.uid;
- if(duplicateCheck[tmpUID] == undefined) {
- addVertex(context, mVertexBuffer, face.v3, face.uv3, face);
- duplicateCheck[tmpUID] = indexBufferIdx;
- mIndexBuffer.push(indexBufferIdx);
- face.v3.bufferIdx = indexBufferIdx;
- ++indexBufferIdx;
- } else {
- mIndexBuffer.push(duplicateCheck[tmpUID]);
- }
- }
- duplicateCheck = null;
- numIndices = mVertexBuffer.length / shaderData.numFloatsPerVertex;
- // GENERATE BUFFERS
- vertexBuffer = context.createVertexBuffer(numIndices, shaderData.numFloatsPerVertex);
- vertexBuffer.uploadFromVector(mVertexBuffer, 0, numIndices);
- if(!indexBuffer) {
- const mIndexBuffer_length:int = mIndexBuffer.length;
- indexBuffer = context.createIndexBuffer(mIndexBuffer_length);
- indexBuffer.uploadFromVector(mIndexBuffer, 0, mIndexBuffer_length);
- numTris = int(mIndexBuffer_length / 3);
- }
- }
- protected function prepareForRender(context:Context3D):void {
- if(previousTintedState != nodeTinted) {
- shaderData = null;
- initProgram(context);
- previousTintedState = nodeTinted;
- }
- context.setProgram(shaderData.shader);
- context.setBlendFactors(blendMode.src, blendMode.dst);
- if(needUploadVertexBuffer) {
- needUploadVertexBuffer = false;
- vertexBuffer.uploadFromVector(mVertexBuffer, 0, mVertexBuffer.length / shaderData.numFloatsPerVertex);
- }
- }
- public function handleDeviceLoss():void {
- indexBuffer = null;
- vertexBuffer = null;
- mIndexBuffer = null;
- mVertexBuffer = null;
- shaderData = null;
- needUploadVertexBuffer = true;
- }
- public function render(context:Context3D, faceList:Vector.<Face>, startTri:uint, numTris:uint):void {
- generateBufferData(context, faceList);
- prepareForRender(context);
- context.drawTriangles(indexBuffer, startTri * 3, numTris);
- clearAfterRender(context);
- }
- protected function clearAfterRender(context:Context3D):void {
- // implement in concrete material
- throw new Error("You have to implement clearAfterRender for your material");
- }
- protected function initProgram(context:Context3D):void {
- // implement in concrete material
- throw new Error("You have to implement initProgram for your material");
- }
- protected function refreshClipspaceMatrix():Matrix3D {
- clipSpaceMatrix.identity();
- clipSpaceMatrix.append(modelMatrix);
- clipSpaceMatrix.append(viewProjectionMatrix);
- return clipSpaceMatrix;
- }
- protected function addVertex(context:Context3D, buffer:Vector.<Number>, v:Vertex, uv:UV, face:Face):void {
- // implement in concrete material
- throw new Error("You have to implement addVertex for your material");
- }
- protected function fillBuffer(buffer:Vector.<Number>, v:Vertex, uv:UV, face:Face, semanticsID:String, floatFormat:int):void {
- if(semanticsID == VERTEX_POSITION) {
- buffer.push(v.x, v.y);
- if(floatFormat >= 3)
- buffer.push(v.z);
- if(floatFormat == 4)
- buffer.push(v.w);
- }
- if(semanticsID == VERTEX_UV) {
- buffer.push(uv.u, uv.v);
- if(floatFormat == 3)
- buffer.push(0.0);
- if(floatFormat == 4)
- buffer.push(0.0, 0.0);
- }
- if(semanticsID == VERTEX_COLOR) {
- buffer.push(v.r, v.g, v.b);
- if(floatFormat == 4)
-