1. 程式人生 > >cocos2dx 渲染DDS格式紋理

cocos2dx 渲染DDS格式紋理

DDS簡介:DDS檔案格式要追述到S3(Silicon & Software Systems)公司提出的一種紋理壓縮格式S3TC(S3 Texture Compression), 其目的是通過對紋理的壓縮, 以達到節約系統頻寬並提高效能的目的. S3TC就是通過壓縮方式, 利用有限的紋理快取空間來儲存更多的紋理, 因為它支援6:1的壓縮比例, 所以6M的紋理可以被壓縮為1M存放在材質快取中, 從而在節約了快取的同時也提高了顯示效能. 後來的DXTC和FXT1都是與S3TC類似的技術, 它們分別是微軟和3dfx開發的紋理壓縮標準, FXT1能提供比S3TC更高的壓縮比, 達到8:1, 同時它也在3DFX新版本的Glide中得到支援. DXTC是1999年微軟從S3公司取得S3TC的授權後更名而來的, 並在DirectX6中提供了支援, 即使使用者的圖形硬體不能支援S3TC, DirectX API會自動解碼壓縮後的紋理貼圖. 壓縮紋理貼圖可以使用高品質的離線壓縮器, 不會造成載入程式時有很多延時, 而DDS檔案就可以使用DXTC方式壓縮或是儲存未壓縮的畫素格式.
簡單的說 DDS紋理的特性是佔用磁碟空間大,但其紋理壓縮格式的特性,可以節約快取使佔用記憶體大大降低,一些3D建模遊戲會運用DDS貼圖,提高遊戲技能,順暢度也大幅提高。


我對於DDS紋理貼圖的研究其實源於專案的需求。先來講個故事:BOSS某天給我指派了一個任務,大概是你看別人家的遊戲為什麼如此順暢,你來研究一下別人用了什麼框架,什麼技術然後需要用扒到的素材做出一款簡化的demo。(求當是我心裡的陰影面積)我當是還是蠻激動的,因為畢竟不用去做瑣碎無聊的事,也可趁此機會也可以學習下其他的框架。
在chrome偵錯程式中扒到得資源裡的DDS格式檔案,此類檔案可以下載一個XnView軟體工具直接開啟檢視,或者下載一個可以安裝到Photoshop中的s3tc格式的外掛。
cocos2dx如何載入DDS紋理:(這裡我用的JS指令碼)
1.Native載入
對於JSBinding來說,載入很方便。因為cocos底層有直接解壓縮S3TC壓縮格式的函式。可以直接採用用路徑名建立精靈
如:var spr = new cc.sprite(“res/test.dds”);
與載入png的方式並無差異,將精靈加在顯示的layer上,可以直接看到載入DDS紋理的圖片。
2.H5載入

說來很奇怪,cocos html並沒有提供可以直接載入DDS檔案格式的函式。若是如Native那樣載入,會出現“.dds檔案型別不能識別的錯誤。”
網上可供參考的資料少之又少,通過對OpenGL渲染紋理的瞭解和對底層程式碼的分析,終於將DDS貼圖渲染出來,顯示在我的TestLayer上。
這裡貼出程式碼:

_getSourceBuffer: function(){
        var self = this;
        var xhr = new XMLHttpRequest();
        xhr.addEventListener('load', function
(ev) {
console.log("xhr resp"); if (xhr.status == 200) { self.parseDDS(xhr.response, self._uploadCallback, errorCallback, ""); } else { errorCallback(xhr.statusText); } }, false); xhr.open('GET', "res/test.dds", true); xhr.responseType = 'arraybuffer'; xhr.send(null); }

getSourceBuffer函式是採用XMLHttpRequest的方式讀取出test.dds的ArrayBuffer,即二進位制的原始快取資料。

parseDDS: function(arrayBuffer, callback, errorCallback, desc) {
        console.log("parseDDS");
        if (!callback || !errorCallback) {
            return
        }
        var header = new Int32Array(arrayBuffer, 0, DDS_HEADER_LENGTH);
        if (header[DDS_HEADER_MAGIC] != DDS_MAGIC) {
            errorCallback("Invalid magic number in DDS header");
            return 0
        }
        if (!header[DDS_HEADER_PF_FLAGS] & DDPF_FOURCC) {
            errorCallback("Unsupported format, must contain a FourCC code");
            return 0
        }
        var fourCC = header[DDS_HEADER_PF_FOURCC];
        var internalFormat;
        switch (fourCC) {
            case FOURCC_DXT1:
                internalFormat = COMPRESSED_RGB_S3TC_DXT1_EXT;
                break;
            case FOURCC_DXT3:
                internalFormat = COMPRESSED_RGBA_S3TC_DXT3_EXT;
                break;
            case FOURCC_DXT5:
                internalFormat = COMPRESSED_RGBA_S3TC_DXT5_EXT;
                break;
            case FOURCC_ATC:
                internalFormat = COMPRESSED_RGB_ATC_WEBGL;
                break;
            case FOURCC_ATCA:
                internalFormat = COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL;
                break;
            case FOURCC_ATCI:
                internalFormat = COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL;
                break;
            default:
                errorCallback("Unsupported FourCC code: " + int32ToFourCC(fourCC));
                return
        }
        var levels = 1;
        if (header[DDS_HEADER_FLAGS] & DDSD_MIPMAPCOUNT) {
            levels = Math.max(1, header[DDS_HEADER_MIPMAPCOUNT])
        }
        var width = header[DDS_HEADER_WIDTH];
        var height = header[DDS_HEADER_HEIGHT];
        var dataOffset = header[DDS_HEADER_SIZE] + 4;
        var dxtData = new Uint8Array(arrayBuffer, dataOffset);

        var B0 = this.textureLevelSize(internalFormat, width, height)
        var A0 = new Uint8Array(dxtData.buffer,dxtData.byteOffset,B0);

        this.initWithData(A0,internalFormat,width,height,cc.size(width,height));
        if(callback) callback();
    },

parseDDS函式的功能是將上述得到的二進位制快取陣列進行解析,獲得人力的width,height,size和紋理資料塊壓縮格式等資訊,再通過initWithData進行Texture2D的初始化:

initWithData: function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) {
        var self = this, tex2d = cc.Texture2D;
        var gl = cc._renderContext;
        var format = gl.RGBA, type = gl.UNSIGNED_BYTE;

        var bitsPerPixel = cc.Texture2D._B[pixelFormat];

        var bytesPerRow = pixelsWide * bitsPerPixel / 8;
        if (bytesPerRow % 8 === 0) {
            gl.pixelStorei(gl.UNPACK_ALIGNMENT, 8);
        } else if (bytesPerRow % 4 === 0) {
            gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
        } else if (bytesPerRow % 2 === 0) {
            gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2);
        } else {
            gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
        }

        self._webTextureObj = gl.createTexture();
        cc.glBindTexture2D(self);

        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

        var ext = (
        gl.getExtension("WEBGL_compressed_texture_s3tc") ||
        gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") ||
        gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc")
        );

        // Specify OpenGL texture image
        switch (pixelFormat) {
            case tex2d.PIXEL_FORMAT_RGBA8888:
                format = gl.RGBA;
                break;
            case tex2d.PIXEL_FORMAT_RGB888:
                format = gl.RGB;
                break;
            case tex2d.PIXEL_FORMAT_RGBA4444:
                type = gl.UNSIGNED_SHORT_4_4_4_4;
                break;
            case tex2d.PIXEL_FORMAT_RGB5A1:
                type = gl.UNSIGNED_SHORT_5_5_5_1;
                break;
            case tex2d.PIXEL_FORMAT_RGB565:
                type = gl.UNSIGNED_SHORT_5_6_5;
                break;
            case tex2d.PIXEL_FORMAT_AI88:
                format = gl.LUMINANCE_ALPHA;
                break;
            case tex2d.PIXEL_FORMAT_A8:
                format = gl.ALPHA;
                break;
            case tex2d.PIXEL_FORMAT_I8:
                format = gl.LUMINANCE;
                break;
            case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
                format = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
                break;
            default:
                cc.assert(0, cc._LogInfos.Texture2D_initWithData);
        }
        if(format == ext.COMPRESSED_RGBA_S3TC_DXT5_EXT){
            //gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, pixelsWide, pixelsHigh, 0, format, type, data);
            gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, pixelsWide, pixelsHigh, 0, data);
        }else{
            gl.texImage2D(gl.TEXTURE_2D, 0, format, pixelsWide, pixelsHigh, 0, format, type, data);
        }


        self._contentSize.width = contentSize.width;
        self._contentSize.height = contentSize.height;
        self._pixelsWide = pixelsWide;
        self._pixelsHigh = pixelsHigh;
        self._pixelFormat = pixelFormat;
        self.maxS = contentSize.width / pixelsWide;
        self.maxT = contentSize.height / pixelsHigh;

        self._hasPremultipliedAlpha = false;
        self._hasMipmaps = false;
        self.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE);

        self._textureLoaded = true;

        return true;
    }

至此一個已將DDS格式紋理解析好的資料初始化了一個Texture2D的物件,初始化流程參考OPENGL基本渲染流程和cocos引擎底層對cc.Texture2D的渲染流程。

再用解析渲染後的Texture建立精靈,addChild在layer上即可顯示與場景之中。

附:解析所需其他巨集的定義

function fourCCToInt32(value) {
    return value.charCodeAt(0) +
        (value.charCodeAt(1) << 8) +
        (value.charCodeAt(2) << 16) +
        (value.charCodeAt(3) << 24);
}

var FOURCC_DXT1 = fourCCToInt32("DXT1");
var FOURCC_DXT3 = fourCCToInt32("DXT3");
var FOURCC_DXT5 = fourCCToInt32("DXT5");

var FOURCC_ATC = fourCCToInt32("ATC ");
var FOURCC_ATCA = fourCCToInt32("ATCA");
var FOURCC_ATCI = fourCCToInt32("ATCI");

// DXT formats, from:
// http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
var COMPRESSED_RGB_S3TC_DXT1_EXT  = 0x83F0;
var COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
var COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
var COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;

// ATC formats, from:
// http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_atc/
var COMPRESSED_RGB_ATC_WEBGL                     = 0x8C92;
var COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL     = 0x8C93;
var COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;

var DDS_MAGIC = 0x20534444;
var DDSD_MIPMAPCOUNT = 0x20000;
var DDPF_FOURCC = 0x4;

var DDS_HEADER_LENGTH = 31; // The header length in 32 bit ints.

// Offsets into the header array.
var DDS_HEADER_MAGIC = 0;

var DDS_HEADER_SIZE = 1;
var DDS_HEADER_FLAGS = 2;
var DDS_HEADER_HEIGHT = 3;
var DDS_HEADER_WIDTH = 4;

var DDS_HEADER_MIPMAPCOUNT = 7;

var DDS_HEADER_PF_FLAGS = 20;
var DDS_HEADER_PF_FOURCC = 21;

相關推薦

cocos2dx 渲染DDS格式紋理

DDS簡介:DDS檔案格式要追述到S3(Silicon & Software Systems)公司提出的一種紋理壓縮格式S3TC(S3 Texture Compression), 其目的是通過對紋理的壓縮, 以達到節約系統頻寬並提高效能的目的. S3TC

65 - three.js 筆記 - 載入 DDS 格式紋理

1、DDS紋理格式 首先,圖片轉換成dds格式,佔用磁碟會變大,但是轉換成dds格式之後架載入到記憶體和視訊記憶體的佔用量會變小。 1.1、dds格式簡介 DDS格式要追述到S3(Silicon & Software Systems)公司提出的一種紋理壓縮格式S3TC(S

m3u8編碼視頻webgl、threejs渲染視頻紋理demo

brush dom sets get html png true -a har <!DOCTYPE html> <html> <head> <meta charset=utf-8 /> <title>fz-liv

D3D12渲染技術之紋理案例

我們現在回顧一下將紋理新增到箱子模型上面,就跟以前的部落格中提到的那樣。下面我們詳細介紹如何實現? 指定紋理座標 GeometryGenerator :: CreateBox生成箱子的紋理座標,以便將整個紋理影象對映到箱子的每個面上。 為簡潔起見,我們僅顯示正面,背面和頂面的頂點

cocos2dx渲染架構

2dx的時代UI樹便利和渲染是沒有分開的,遍歷UI樹的時候就渲染.3dx版本為了分離了ui樹的遍歷和渲染,先遍歷生成渲染命令發到渲染佇列,之後遍歷渲染命令佇列開始渲染.這樣做的好處是渲染命令可以重用,單獨的渲染可以做優化例如自動批繪製.本篇首先介紹cocos2D-X 3.x版本的渲染結構,之後會深入openg

bytemode stay hungry stay foolish cocos2dx渲染架構

  2dx的時代UI樹便利和渲染是沒有分開的,遍歷UI樹的時候就渲染.3dx版本為了分離了ui樹的遍歷和渲染,先遍歷生成渲染命令發到渲染佇列,之後遍歷渲染命令佇列開始渲染.這樣做的好處是渲染命令可以重用,單獨的渲染可以做優化例如自動批繪製.本篇首先介紹cocos2D-X 3.x版本的渲染結構,之後會

D3D渲染技術之紋理

紋理對映是一種將影象資料對映到三角形上的技術,從而能增加場景的細節和真實感。 例如,我們可以通過在每一側繪製板條紋理來構建一個立方體並將其轉換為板條箱如下圖所示。 在這裡給讀者教讀者如何學習紋理技術: 1、要了解如何指定對映到三角形的紋理部分。 2、瞭解如何建

D3D12渲染技術之紋理資料來源

為遊戲建立紋理的最流行的方法是讓美工在Photoshop或其他影象編輯器中製作它們,然後將它們儲存為影象檔案,如BMP,DDS,TGA或PNG。 遊戲應用程式將載入時的影象資料載入到ID3D12Resource物件中, 對於實時圖形應用程式,DDS(Direct

D3D12渲染技術之紋理座標

Direct3D使用紋理座標系,該座標系包含一個水平延伸到影象的u軸和一個垂直於影象執行的v軸。 座標(u,v)使得0≤u,v≤1,紋理上稱為紋理畫素的元素。 請注意,v軸在“向下”方向上為正(見下圖)。 另外,請注意使用的歸一化座標間隔[0,1],因為它為Di

OpenGL載入DDS壓縮紋理

網路上的影象庫很多,如 FreeImage 、 Devil 等,庫很強大且支援多種格式,當然也包括 DDS 紋理。例如 FreeImage ,但是它這裡所說的支援 DDS 格式是指將壓縮格式的資料重新解壓成 RGBA 畫素資料,將資料解壓後再繫結到 OpenGL 中就失去了

Qt 使用openGL 渲染NV12格式的視頻

bind oat vertex del rgb 繼承 har cti for 直接上代碼 Nv12Render.h #ifndef NV12RENDER_H #define NV12RENDER_H #include <QOpenGLFunctions> #i

cocos2dx-使用16-bit紋理顯示圖片

使用16-bit紋理 最快速地減少紋理記憶體佔用的辦法就是把它們作為16位顏色深度的紋理來載入。cocos2d預設的紋理畫素格式是32位顏色深度。如果把顏色深度減半,那麼記憶體消耗也就可以減少一半。並且這還會帶來渲染效率的提升,大約提高10%。 你可以使用CCText

opengl es 渲染方式與 紋理座標設定 ,OpenGL ES 模型檢視之縮放操作

OpenGl ES關於渲染方式有以下兩種: RENDERMODE_CONTINUOUSLY和RENDERMODE_WHEN_DIRTY。 預設渲染方式為RENDERMODE_CONTINUOUSLY,這兩種渲染的含義是: RENDERMODE_CONTINUOUSL

cocos2dx Sprite使用同一張紋理會只調用一次渲染

cocos2dx3.x中,Sprite呼叫draw函式時會新增一個TrianglesCommand型別的渲染指令。 CCSprite.cpp _trianglesCommand.init(_globalZOrder, _text

【小松教你手遊開發】【遊戲渲染】單色shader,紋理shader

無單色shader Shader "ChrisShader/OneColorShader" { Properties { _Color ("color", Color) = (0,0,0,0) } SubShader {

使用渲染紋理的制作攝像頭

-a 控制 pan 紅外 security app for 說明 answer https://www.cnblogs.com/chenliyang/p/6558455.html 使用渲染紋理的制作攝像頭 從Unity5版本開始,渲染紋理的功能對所有用戶開放(是的,包括免費

[圖形學] 經典演算法 - Kajiya三維紋理渲染毛髮

簡介         渲染複雜度高細節豐富的場景一直是影象繪製的重要目標。一個想法是引入不同尺度的層次,每一層次對應一種精度幾何模型。因此那些複雜的小物體可以被歸類為可被簡化的幾何物體。         但是,繪

多種紋理的複雜組合在渲染系統中的應用: WebGL演示

Demo:http://www.artvily.com/sample?sample=combinationTex 紋理作為幾何體表面的表現資料來源的主力,很多地方需要用到。有時候需要用到多種紋理物件,例如一維二維三維紋理同在一個shader中用到,就需要渲染系統對紋理源的靈活的支援。在我的

jQuery+Ajax+js請求json格式資料並渲染到html頁面

1、先給json格式的資料: [ {"id":1,"name":"stan"}, {"id":2,"name":"jack"}, {"id":3,"name":"lucy"}, {"id":4,"name":"mary"}, {"id":5,"name":"jerry"}, {"id":6,"n

Unity3D設定紋理格式

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!