Created
April 2, 2017 10:04
-
-
Save mieki256/7f1f941f74fd9d62d2607d674465f380 to your computer and use it in GitHub Desktop.
DXRubyでフォンシェーディングのテスト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!ruby -Ku | |
# -*- mode: ruby; coding: utf-8 -*- | |
# Last updated: <2017/04/02 16:12:04 +0900> | |
# | |
# DXRuby 1.5.21dev以降で追加された CustomRenderTarget の動作確認 | |
# 公式サンプル spheretest.rb を改造 | |
# | |
# tinydaeparser.rb や tinywavefrontobj.rb を使って | |
# COLLADA形式(.dae) や Wavefront形式(.obj .mtl)を直接読んで使ってみる | |
# | |
# フォンシェーディングにも対応…できたのだろうか…自信無い | |
# | |
# * カーソルキーでモデルを回転できるように変更 | |
# * W,Sキーで前後に移動 | |
# * A,Dキーで鏡面光の硬度を変更できる | |
# | |
# usage: | |
# ruby crt_test06_readdae.rb [0-5] | |
# | |
# DXRuby開発版の入手先 | |
# Home - mirichi/dxruby-doc Wiki | |
# https://github.com/mirichi/dxruby-doc/wiki | |
require 'dxruby' | |
require 'json' | |
require 'pp' | |
require_relative 'tinydaeparser' | |
require_relative 'tinywavefrontobj' | |
# モデルデータの頂点配列やシェーダを格納するクラス | |
class Material | |
attr_accessor :vbuf0 | |
attr_accessor :vbuf1 | |
attr_accessor :vbuf2 | |
attr_accessor :vbuf3 | |
attr_accessor :shader | |
attr_accessor :m | |
# @return [true, false] テクスチャを使っているか否か | |
attr_accessor :use_uv | |
# @return [Image] テクスチャ画像 | |
attr_accessor :image | |
# HLSLソースのリスト | |
HLSL_LIST = { | |
:lambert => "hlsl_lambert.fx", | |
:phong => "hlsl_phong.fx", | |
} | |
# SHADING = :lambert | |
SHADING = :phong | |
@@hlsl = nil | |
# initialize | |
# | |
# @param vertex [Array<Float>] 頂点座標配列 | |
# @param normal [Array<Float>] 法線ベクトル配列 | |
# @param uv [Array<Float>] uv座標配列 | |
# @param color [Array<Integer>] 頂点カラー配列 | |
# @param image [Image, nil] テクスチャ画像。nilならuvは使わない | |
# @param ambient [Vector] 環境光 | |
# @param diffuse [Vector] 拡散光 | |
# @param specular [Vector] 鏡面光 | |
# @param shininess [Float] 鏡面強度(鏡面硬度?)、0.0-128.0まで | |
# | |
def initialize(vertex: nil, normal: nil, uv: nil, color: nil, image: nil, | |
ambient: nil, diffuse: nil, specular: nil, shininess: 0.0) | |
unless @@hlsl | |
# HLSソースの読み込み | |
@@hlsl = {} | |
HLSL_LIST.each { |k, fn| @@hlsl[k] = File.read(fn) } | |
end | |
@use_uv = (image != nil)? true : false | |
@vertex = vertex | |
@normal = normal | |
@uv = uv | |
@color = color | |
@image = image | |
@mat_ambient = (ambient)? ambient : Vector.new(1.0, 1.0, 1.0) | |
@mat_diffuse = (diffuse)? diffuse : Vector.new(1.0, 1.0, 1.0) | |
@mat_specular = (specular)? specular : Vector.new(0.0, 0.0, 0.0) | |
@mat_shininess = shininess | |
if shininess == 0.0 or !specular | |
# shininessが0なら鏡面光は無しにする | |
@mat_specular = Vector.new(0.0, 0.0, 0.0) | |
end | |
if @use_uv | |
# テクスチャ使用 | |
init_use_tex(@vertex, @normal, @uv, @color, @image) | |
else | |
# テクスチャ未使用 | |
init_not_use_tex(@vertex, @normal, @color) | |
end | |
@shader.vMatAmbient = @mat_ambient | |
@shader.vMatDiffuse = @mat_diffuse | |
@shader.vMatSpecular = @mat_specular | |
@shader.vMatShininess = @mat_shininess | |
end | |
# テクスチャ使用時の初期化処理 | |
# @param vtx [Array<Float>] 頂点座標配列 | |
# @param nml [Array<Float>] 法線ベクトル配列 | |
# @param uv [Array<Float>] uv座標配列 | |
# @param col [Array<Integer>] 頂点カラー配列 | |
# @param img [Image] テクスチャ画像 | |
def init_use_tex(vtx, nml, uv, col, img) | |
# Shader::Core生成 | |
@core = Shader::Core.new(@@hlsl[SHADING], | |
mWorld: :float, | |
mView: :float, | |
mProj: :float, | |
vLightDir: :float, | |
vLightAmbient: :float, | |
vLightDiffuse: :float, | |
vMatAmbient: :float, | |
vMatDiffuse: :float, | |
vMatSpecular: :float, | |
vMatShininess: :float, | |
tex0: :texture | |
) | |
# 頂点座標、法線ベクトル、テクスチャ座標、頂点カラー用バッファ | |
@vbuf0 = VertexBuffer.new([[D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_POSITION, 0],]) | |
@vbuf1 = VertexBuffer.new([[D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_NORMAL, 0],]) | |
@vbuf2 = VertexBuffer.new([[D3DDECLTYPE_FLOAT2, D3DDECLUSAGE_TEXCOORD, 0],]) | |
@vbuf3 = VertexBuffer.new([[D3DDECLTYPE_D3DCOLOR, D3DDECLUSAGE_COLOR, 0],]) | |
@vbuf0.vertices = vtx | |
@vbuf1.vertices = nml | |
@vbuf2.vertices = uv | |
@vbuf3.vertices = col | |
@m = Matrix.new | |
@shader = Shader.new(@core, "WithTex") | |
@shader.tex0 = img | |
end | |
# テクスチャ未使用時の初期化処理 | |
# @param vtx [Array<Float>] 頂点座標配列 | |
# @param nml [Array<Float>] 法線ベクトル配列 | |
# @param col [Array<Integer>] 頂点カラー配列 | |
def init_not_use_tex(vtx, nml, col) | |
@core = Shader::Core.new(@@hlsl[SHADING], | |
mWorld: :float, | |
mView: :float, | |
mProj: :float, | |
vLightDir: :float, | |
vLightAmbient: :float, | |
vLightDiffuse: :float, | |
vMatAmbient: :float, | |
vMatDiffuse: :float, | |
vMatSpecular: :float, | |
vMatShininess: :float | |
) | |
# 頂点座標、法線ベクトル、頂点カラー用バッファ | |
@vbuf0 = VertexBuffer.new([[D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_POSITION, 0],]) | |
@vbuf1 = VertexBuffer.new([[D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_NORMAL, 0],]) | |
@vbuf2 = VertexBuffer.new([[D3DDECLTYPE_D3DCOLOR, D3DDECLUSAGE_COLOR, 0],]) | |
@vbuf0.vertices = vtx | |
@vbuf1.vertices = nml | |
@vbuf2.vertices = col | |
@m = Matrix.new | |
@shader = Shader.new(@core, "WithoutTex") | |
end | |
# 鏡面強度の再設定 | |
# @param shininess [Float] 鏡面強度 0から128まで。0なら鏡面光無しに設定 | |
def set_shininess(shininess) | |
@mat_shininess = shininess | |
@shader.vMatShininess = @mat_shininess | |
if shininess == 0.0 | |
@shader.vMatSpecular = Vector.new(0.0, 0.0, 0.0) | |
else | |
@shader.vMatSpecular = @mat_specular | |
end | |
end | |
# 鏡面強度を取得 | |
def get_shininess | |
return @mat_shininess | |
end | |
end | |
# RenderTarget3Dクラス | |
class RenderTarget3D < CustomRenderTarget | |
attr_accessor :view | |
attr_accessor :proj | |
attr_accessor :light_dir | |
attr_accessor :light_diffuse | |
attr_accessor :light_ambient | |
def initialize(*) | |
super | |
@draw_data = [] # 描画予約的な配列 | |
@light_ambient = Vector.new(0.1, 0.1, 0.1) | |
@light_diffuse = Vector.new(0.9, 0.9, 0.9) | |
end | |
# CustomRenderTargetの描画メソッド | |
def custom_render(o) | |
o.set_viewport(0, 0, width, height, 0, 1) # ビューポート設定 | |
o.begin_scene # 描画開始 | |
# レンダーステート設定 | |
o.set_render_state(D3DRS_CULLMODE, D3DCULL_CW) | |
# o.set_render_state(D3DRS_CULLMODE, D3DCULL_NONE) | |
o.set_render_state(D3DRS_ZENABLE, D3DZB_TRUE) | |
o.set_render_state(D3DRS_ZWRITEENABLE, 1) # bool値 TRUE=1, FALSE=0 | |
# 描画予約を順番に処理する | |
@draw_data.each do |mat| | |
# シェーダパラメータ設定 | |
mat.shader.mWorld = mat.m | |
mat.shader.mView = @view | |
mat.shader.mProj = @proj | |
mat.shader.vLightDir = @light_dir | |
mat.shader.vLightAmbient = @light_ambient | |
mat.shader.vLightDiffuse = @light_diffuse | |
if mat.use_uv | |
# テクスチャ使用 | |
# シェーダパラメータのDirectXへの設定など面倒なことはusing_shaderがやってくれる | |
o.using_shader(mat.shader) do | |
# 頂点バッファは複数指定できる | |
o.set_stream(mat.vbuf0, mat.vbuf1, mat.vbuf2, mat.vbuf3) | |
o.draw_primitive(D3DPT_TRIANGLELIST, mat.vbuf0.vertex_count / 3) | |
end | |
else | |
# テクスチャ未使用 | |
o.using_shader(mat.shader) do | |
o.set_stream(mat.vbuf0, mat.vbuf1, mat.vbuf2) | |
o.draw_primitive(D3DPT_TRIANGLELIST, mat.vbuf0.vertex_count / 3) | |
end | |
end | |
end | |
o.end_scene # 描画終了 | |
@draw_data.clear # 描画予約のクリア | |
end | |
# 描画予約 | |
# @param material [Object] 描画したいモデル | |
def draw(material) | |
@draw_data << material | |
end | |
end | |
# ---------------------------------------- | |
# initialize | |
model_list = [ | |
# [モデルデータファイル名, テクスチャ画像ファイル名] | |
["res/sample_cube_tex.obj", "res/UVCheckerMap01-1024.png"], # 0 cube。テクスチャ使用 | |
["res/suzanne.obj", "res/UVCheckerMap01-1024.png"], # 1 スザンヌ。テクスチャ使用 | |
["res/sample_bg2.dae", "res/uv_mecha.png"], # 2 BGモデル。テクスチャ使用 | |
["res/uv_vcol.dae", "res/uvchecker512.png"], # 3 cube。頂点カラー使用 | |
["res/sample_cube_color.obj", ""], # 4 cube。テクスチャ未使用 | |
["res/ball.dae", "res/uvchecker512.png"], # 5 ball。スムーズ使用 | |
["res/plane.obj", "res/uvchecker512.png"], # 6 plane。只の板 | |
] | |
mkind = 0 | |
# コマンドライン引数で描画するモデルデータを変更 | |
mkind = (ARGV[0].to_i % model_list.size) unless ARGV.empty? | |
model_name, tex_name = model_list[mkind] | |
if model_name =~ /\.dae$/ | |
# モデルデータ(.dae)を読み込み | |
o = TinyDaeParser.new(model_name, dxruby: true) | |
matnames = o.get_material_name_list # マテリアル名リストを取得 | |
matname = matnames[0] # 仮で一番最初のマテリアルのみ使う | |
matdata = o.get_material_data(matname) # マテリアル情報取得 | |
# pp matdata | |
elsif model_name =~ /\.obj$/ | |
# モデルデータ(.obj)を読み込み | |
o = TinyWaveFrontObj.new(model_name, dxruby: true) | |
end | |
# テクスチャ画像読み込み | |
img = (o.use_uv and tex_name != "")? Image.load(tex_name) : nil | |
# モデルデータクラスを生成 | |
material = Material.new( | |
vertex: o.get_vertex_array, # 頂点座標配列 | |
normal: o.get_normal_array, # 法線ベクトル配列 | |
uv: o.get_uv_array, # UV座標配列 | |
color: o.get_color_array, # 頂点カラー配列 | |
image: img, # テクスチャ画像 or nil | |
ambient: Vector.new(1.0, 1.0, 1.0), # 環境光 | |
diffuse: Vector.new(1.0, 1.0, 1.0), # 拡散光 | |
specular: Vector.new(0.5, 0.5, 0.5), # 鏡面光 | |
shininess: 50.0, # 鏡面強度(鏡面硬度?) | |
) | |
# 画面サイズ | |
Window.resize(640, 480) | |
Window.bgcolor = [64, 96, 128] # background color R,G,B | |
# モデル回転用 | |
m_rot_x = 0 | |
m_rot_y = 0 | |
m_move_z = -2.5 | |
# RenderTarget3Dオブジェクト生成 | |
rt3d = RenderTarget3D.new(Window.width, Window.height) | |
rt3d.view = Matrix.look_at( | |
Vector.new(0, 0, m_move_z), # 視点位置 | |
Vector.new(0, 0, 0), # 注視座標 | |
Vector.new(0, 1, 0) # 上方向 | |
) | |
rt3d.proj = Matrix.projection_fov( | |
60.0, # 視野角 | |
Window.width.to_f / Window.height, # 画面比 | |
0.5, # near clip | |
1000.0 # far clip | |
) | |
# ライト方向(頂点から光源に向けたベクトル)等を設定 | |
rt3d.light_dir = Vector.new(0.5, 0.5, -1).normalize | |
rt3d.light_ambient = Vector.new(0.1, 0.1, 0.1) | |
rt3d.light_diffuse = Vector.new(0.9, 0.9, 0.9) | |
fnt = Font.new(12) | |
# メインループ | |
Window.loop do | |
break if Input.keyPush?(K_ESCAPE) | |
# ライト位置、じゃなくてライト方向をマウス座標で変更。 | |
# 頂点から光源に向けたベクトルで、光源から頂点へ、ではないっぽい。 | |
x = Input.mouse_x.fdiv(Window.width / 2) - 1 | |
y = -(Input.mouse_y.fdiv(Window.height / 2) - 1) | |
rt3d.light_dir = Vector.new(x, y, -1).normalize | |
# phongシェーディングのshininess(鏡面強度、鏡面指数)を変更 | |
if Input.keyDown?(K_D) or Input.keyDown?(K_A) | |
shininess = material.get_shininess + 2 * ((Input.keyDown?(K_D))? 1 : -1) | |
shininess = 0.0 if shininess < 0.0 | |
shininess = 128.0 if shininess > 128.0 | |
material.set_shininess(shininess) | |
end | |
# カメラ位置(奥行き)変更 | |
if Input.keyDown?(K_W) or Input.keyDown?(K_S) | |
m_move_z += 0.1 * ((Input.keyDown?(K_W))? -1 : 1) | |
rt3d.view = Matrix.look_at( | |
Vector.new(0, 0, m_move_z), | |
Vector.new(0, 0, 0), | |
Vector.new(0, 1, 0) | |
) | |
end | |
# マテリアル(モデルデータ)をカーソルキーの入力で回転 | |
d = 2.0 | |
m_rot_x += Input.y.to_f * d | |
m_rot_y += Input.x.to_f * d | |
material.m = Matrix.new | |
material.m *= Matrix.rotation_x(m_rot_x) | |
material.m *= Matrix.rotation_y(m_rot_y) | |
# RenderTarget3Dにモデルを描画 | |
rt3d.draw(material) | |
# 画面に描画 | |
Window.draw(0, 0, rt3d) | |
# FPS等を描画 | |
Window.drawFont(4, 4, sprintf("%02d fps", Window.fps), fnt) | |
Window.drawFont(4, 24, "Push Arrow Key or W,D", fnt) | |
Window.drawFont(4, 44, "shininess = #{material.get_shininess}", fnt) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// HLSL lambert shading (half lambert) | |
float4x4 mWorld; | |
float4x4 mView; | |
float4x4 mProj; | |
float4 vLightDir; // light direction | |
float3 vLightAmbient; // light ambient | |
float3 vLightDiffuse; // light diffuse | |
float3 vMatAmbient; // matrial ambient | |
float3 vMatDiffuse; // material diffuse | |
float3 vMatSpecular; // material specular | |
float vMatShininess; // material shininess | |
texture tex0; // texture image | |
sampler2D Samp = sampler_state { | |
Texture = <tex0>; | |
}; | |
struct VS_IN { | |
float4 vPosition : POSITION0; // vertex position | |
float4 vNormal : NORMAL; // vertex normal | |
float2 vTexCoords : TEXCOORD0; // texture uv | |
float4 vVertexColor : COLOR0; // vertex color | |
}; | |
struct VS_IN_WOT { | |
float4 vPosition : POSITION0; // vertex position | |
float4 vNormal : NORMAL; // vertex normal | |
float4 vVertexColor : COLOR0; // vertex color | |
}; | |
struct VS_OUT { | |
float4 vPosition : POSITION; // vertex position | |
float3 vNormal : TEXCOORD0; // vertex normal | |
float2 vTexCoords : TEXCOORD1; // texture uv | |
float4 vVertexColor : COLOR0; // vertex color | |
}; | |
struct VS_OUT_WOT { | |
float4 vPosition : POSITION; // vertex position | |
float3 vNormal : TEXCOORD0; // vertex normal | |
float4 vVertexColor : COLOR0; // vertex color | |
}; | |
// vertex shader with txeture | |
VS_OUT VS(VS_IN v) { | |
VS_OUT output; | |
output.vPosition = mul(mul(mul(v.vPosition, mWorld), mView), mProj); | |
output.vNormal = mul(v.vNormal, mWorld).xyz; | |
output.vVertexColor = v.vVertexColor; | |
output.vTexCoords = v.vTexCoords.xy; | |
return output; | |
} | |
// vertex shader without txeture | |
VS_OUT_WOT VS_WOT(VS_IN_WOT v) { | |
VS_OUT_WOT output; | |
output.vPosition = mul(mul(mul(v.vPosition, mWorld), mView), mProj); | |
output.vNormal = mul(v.vNormal, mWorld).xyz; | |
output.vVertexColor = v.vVertexColor; | |
return output; | |
} | |
struct PS_OUT { | |
float4 vColor : COLOR0; | |
}; | |
// pixel shader with tex | |
PS_OUT PS(VS_OUT p) { | |
PS_OUT output; | |
float4 tcolor = tex2D(Samp, p.vTexCoords); | |
float lambert = dot(vLightDir, normalize(p.vNormal)) * 0.5f + 0.5f; | |
lambert *= lambert; | |
float3 diffuse = vLightDiffuse * vMatDiffuse * p.vVertexColor * lambert * tcolor; | |
float3 ambient = vLightAmbient * vMatAmbient; | |
output.vColor.rgb = diffuse + ambient; | |
output.vColor.a = 1.0; | |
return output; | |
} | |
// pixel shader without tex | |
PS_OUT PS_WOT(VS_OUT_WOT p) { | |
PS_OUT output; | |
float lambert = dot(vLightDir, normalize(p.vNormal)) * 0.5f + 0.5f; | |
lambert *= lambert; | |
float3 diffuse = vLightDiffuse * vMatDiffuse * p.vVertexColor * lambert; | |
float3 ambient = vLightAmbient * vMatAmbient; | |
output.vColor.rgb = diffuse + ambient; | |
output.vColor.a = 1.0; | |
return output; | |
} | |
technique WithTex { | |
pass p0 { | |
VertexShader = compile vs_2_0 VS(); | |
PixelShader = compile ps_2_0 PS(); | |
} | |
} | |
technique WithoutTex { | |
pass p0 { | |
VertexShader = compile vs_2_0 VS_WOT(); | |
PixelShader = compile ps_2_0 PS_WOT(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// HLSL phong shading | |
float4x4 mWorld; | |
float4x4 mView; | |
float4x4 mProj; | |
float4 vLightDir; // light direction | |
float3 vLightAmbient; // light ambient | |
float3 vLightDiffuse; // light diffuse | |
float3 vMatAmbient; // matrial ambient | |
float3 vMatDiffuse; // material diffuse | |
float3 vMatSpecular; // material specular | |
float vMatShininess; // material shininess | |
texture tex0; // texture image | |
sampler2D Samp = sampler_state { | |
Texture = <tex0>; | |
}; | |
struct VS_IN { | |
float4 vPosition : POSITION0; // vertex position | |
float4 vNormal : NORMAL; // vertex normal | |
float2 vTexCoords : TEXCOORD0; // texture uv | |
float4 vVertexColor : COLOR0; // vertex color | |
}; | |
struct VS_IN_WOT { | |
float4 vPosition : POSITION0; // vertex position | |
float4 vNormal : NORMAL; // vertex normal | |
float4 vVertexColor : COLOR0; // vertex color | |
}; | |
struct VS_OUT { | |
float4 vPosition : POSITION; // vertex position | |
float3 vNormal : TEXCOORD0; // vertex normal | |
float2 vTexCoords : TEXCOORD1; // texture uv | |
float4 vVertexColor : COLOR0; // vertex color | |
float3 vWPos : TEXCOORD2; | |
float3 vEyePos : TEXCOORD3; | |
}; | |
struct VS_OUT_WOT { | |
float4 vPosition : POSITION; // vertex position | |
float3 vNormal : TEXCOORD0; // vertex normal | |
float4 vVertexColor : COLOR0; // vertex color | |
float3 vWPos : TEXCOORD1; | |
float3 vEyePos : TEXCOORD2; | |
}; | |
// vertex shader with texture | |
VS_OUT VS(VS_IN v) { | |
VS_OUT output; | |
output.vTexCoords = v.vTexCoords.xy; | |
output.vPosition = mul(mul(mul(v.vPosition, mWorld), mView), mProj); | |
output.vNormal = mul(v.vNormal, (float3x3)mWorld).xyz; | |
output.vVertexColor = v.vVertexColor; | |
output.vWPos = mul(v.vPosition, mWorld); | |
output.vEyePos = mView[3].xyz; | |
return output; | |
} | |
// vertex shader without texture | |
VS_OUT_WOT VS_WOT(VS_IN_WOT v) { | |
VS_OUT_WOT output; | |
output.vPosition = mul(mul(mul(v.vPosition, mWorld), mView), mProj); | |
output.vNormal = mul(v.vNormal, (float3x3)mWorld).xyz; | |
output.vVertexColor = v.vVertexColor; | |
output.vWPos = mul(v.vPosition, mWorld); | |
output.vEyePos = mView[3].xyz; | |
return output; | |
} | |
struct PS_OUT { | |
float4 vColor : COLOR0; | |
}; | |
// pixel shader with texture | |
PS_OUT PS(VS_OUT p) { | |
PS_OUT output; | |
float4 tcolor = tex2D(Samp, p.vTexCoords); | |
float3 light = normalize(vLightDir.xyz); | |
float3 normal = normalize(p.vNormal); | |
// diffuse | |
// float lambert = clamp(dot(light, normal), 0.0f, 1.0f); | |
float lambert = dot(light, normal) * 0.5f + 0.5f; | |
lambert *= lambert; | |
float3 diffuse = vLightDiffuse * vMatDiffuse * p.vVertexColor * lambert * tcolor; | |
// specular | |
float3 view = normalize(p.vEyePos - p.vWPos); | |
float3 r = normalize(light - 2.0f * normal * dot(light, normal)).xyz; | |
float spe = pow(max(dot(r, view), 0.0f), vMatShininess); | |
// float3 halfway = normalize(light - view); | |
// float spe = pow(max(dot(normal, halfway), 0.0f), vMatShininess); | |
float3 specular = vMatSpecular * spe; | |
// ambient | |
float3 ambient = vLightAmbient * vMatAmbient; | |
output.vColor.rgb = diffuse + specular + ambient; | |
output.vColor.a = 1.0; | |
return output; | |
} | |
// pixel shader without texture | |
PS_OUT PS_WOT(VS_OUT_WOT p) { | |
PS_OUT output; | |
float3 light = normalize(vLightDir.xyz); | |
float3 normal = normalize(p.vNormal); | |
float lambert = dot(light, normal) * 0.5f + 0.5f; | |
lambert *= lambert; | |
float3 diffuse = vLightDiffuse * vMatDiffuse * p.vVertexColor * lambert; | |
float3 view = normalize(p.vEyePos - p.vWPos); | |
float3 r = normalize(light - 2.0f * normal * dot(light, normal)).xyz; | |
float spe = pow(max(dot(r, view), 0.0f), vMatShininess); | |
float3 specular = vMatSpecular * spe; | |
float3 ambient = vLightAmbient * vMatAmbient; | |
output.vColor.rgb = diffuse + specular + ambient; | |
output.vColor.a = 1.0; | |
return output; | |
} | |
// with texture | |
technique WithTex { | |
pass p0 { | |
VertexShader = compile vs_2_0 VS(); | |
PixelShader = compile ps_2_0 PS(); | |
} | |
} | |
// without texture | |
technique WithoutTex { | |
pass p0 { | |
VertexShader = compile vs_2_0 VS_WOT(); | |
PixelShader = compile ps_2_0 PS_WOT(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
動作には tinydaeparser.rb と tinywavefrontobj.rb、サンプルデータ(.dae .obj .mtl)が必要。
mieki256/tinydaeparser
https://github.com/mieki256/tinydaeparser
mieki256/tinywavefrontobj
https://github.com/mieki256/tinywavefrontobj