遊戲畫面的油膩感是從何而來的?

首先題主對任何遊戲都沒有惡意,只是想搞清楚自己疑惑。遊戲里很多應該是濕漉漉或者光滑或者金屬反光的的地方看上去總有種抹了一層油或者打了一層蠟的感覺。還有一個有疑問的地方在很多遊戲里很多盔甲總感覺已經使用的坑坑窪窪了卻沒有什麼劃痕?比如《龍騰世紀 審判》很多地方就給我這種感覺(特別是室內弱光的場景下尤為明顯,遊戲當年在PS3上玩的,現在找圖片貌似渲染圖比較多。真的沒找到圖,如果有哪位找到了可以在編輯問題了補充,謝謝各位了。)。然而《神秘海域4》大多數時候的畫面我是沒這樣的感覺的。請問這種感覺是從何而來,怎麼產生的?


關於畫面油膩感,拋去配色問題的話,我們一般指這樣:

看起來像打蠟的效果,實質上是因為反射高光(specular)的光斑大量存在於不該有反射高光的物體上,使得這類物體表面看起來光滑無比,像抹了油一樣。

除去刻意製造玩偶化角色的遊戲外(事實上很多奇幻類遊戲都傾向於這麼做以減少玩家將人物與現實聯繫起來的心理預期),造成這種問題有兩種可能。

一種可能是圖像引擎技術問題,材質的物理化不足,難以模擬出真實材質該有的反射效果,從而使其錯誤地在渲染中大量使用反射高光。

第二種則可能是圖像引擎過關了,但應用上出現了問題,沒有設置成對應的參數,一樣使物體錯誤地使用反射高光。兩者都能造成油膩感,但後者的出現概率要遠低於前者。

下圖為兩種不同技術下的材質渲染效果的對比。

左為Phong Shading(感謝指正,應為Phong Reflection Model),材質主要使用底光、散射光與反射光等圖形學參數。特點是易實現、效率高。
右為Physically Based Shading,材質主要使用金屬率、粗糙度等物理學參數。特點是真實感強、參數規範(不易出現物理學上不允許的材質),但是運行效率較低,渲染時有時需要額外的外部數據,更依賴性能。

早期大量3D遊戲採用簡單易實現的Phong Shading技術,人物與物體的材質的參數大多是根據經驗所設定,並隨感官修正。這些材質當然會和現實世界有較為明顯的差距。體現在人物皮膚等重要而複雜物體上,錯誤的設定就可能導致材質的反射率等參數與現實不符,導致玩家視覺上的油膩感產生。

事實上物理渲染(Physically Based Rendering)技術的出現徹底讓材質的圖形渲染與物理性質掛鉤,比如粗糙度高的物體散射度更高但反射高光更低,比如任何物體都存在的菲涅爾效果。美術不再需要憑感覺去填材質參數,而是根據真實的物理性質來填寫,大大降低了人工環節犯錯的可能。

也就是說,除非美術犯下大錯,否則多數時候,油膩感就是圖像引擎的鍋。當然,在引擎不變的前提下,油膩感依然是可以修正的,但這要花費開發團隊大量的時間與人力去調試,因此許多開發投入較小的團隊便會戰略性放棄這一塊,甚至一些遊戲將其作為人物形象特點的一部分,讓油膩的師姐在這裡等著你探尋!

取匿了,學生一枚,誤導不負責。


(相片來源 Instagram @leonardhoespams)

這雙腿夠油亮了吧?

我覺得油的感覺主要來自過於平滑表面的鏡面反射(specular reflection)。PBR 對此有更好的控制。


不用 PBR 就是這樣啊……比如有些人可能想做金屬,結果 Fresnel 寫錯了,弄成光滑的塑料


第一,油膩的效果一般是在Shader程序中實現的,那是程序員們智慧的結晶!

第二,如果你對遊戲中油膩感到噁心,這特么都是美術的錯誤,程序是無辜的。

舉個栗子,證明下我的觀點:

Shadertoy BETA

這裡用50多行的Shader代碼生成了一個油膩膩的鼻屎球:

const float PI = 3.14159265359;

vec2 sphere_map(vec3 n) {
return vec2((atan(n.z,n.x)/(2.0 * PI)) + iGlobalTime * 0.05, acos(n.y) / (PI)) + vec2(0.6, 0.0);
}

float scene(vec3 position) {
vec2 uv = sphere_map(normalize(position));
float height = 0.4 - pow(texture2D(iChannel0, uv).x, 3.0) * 0.1;
return length(position)-height;
}

vec3 getNormal(vec3 ray_hit_position, float smoothness) {
vec3 n;
vec2 dn = vec2(smoothness, 0.0);
n.x = scene(ray_hit_position + dn.xyy) - scene(ray_hit_position - dn.xyy);
n.y = scene(ray_hit_position + dn.yxy) - scene(ray_hit_position - dn.yxy);
n.z = scene(ray_hit_position + dn.yyx) - scene(ray_hit_position - dn.yyx);
return normalize(n);
}

float raymarch(vec3 position, vec3 direction) {
float total_distance = 0.0;
for(int i = 0 ; i &< 32 ; ++i) { float result = scene(position + direction * total_distance); if(result &< 0.005) { return total_distance; } total_distance += resu< } return -1.0; } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord.xy / iResolution.y; uv -= vec2(0.5*iResolution.x/iResolution.y, 0.5); vec3 direction = normalize(vec3(uv, 2.5)); vec3 origin = vec3(0.0, 0.0, -2.5); float dist = raymarch(origin, direction); if(dist &< 0.0) { fragColor = vec4(0.0, sin(uv.y+1.0)*0.2, sin(uv.y+1.0)*0.3 ,1.0); } else{ vec3 fragPosition = origin+direction*dist; vec3 N = getNormal(fragPosition, 0.01); vec3 lightPos = vec3(1.0, 0.0, -1.0); float diffuse = dot(normalize(lightPos), N); diffuse = max(0.0, diffuse); vec2 uv = sphere_map(normalize(fragPosition)); vec4 cheeseColor = vec4(0.7, 0.8, 0.0, 1.0) - texture2D(iChannel0, uv).x * vec4(0.9, 0.55, 0.9, 1.0); fragColor = (cheeseColor*diffuse)+vec4(0.2, 0.0, 0.05, 1.0); fragColor += pow(max(0.0,dot(normalize(-reflect(fragPosition-lightPos, N)),normalize(-fragPosition))), 80.0) ; } }

關鍵代碼是最後一句,利用光的反射產生油膩的效果:

fragColor += pow(max(0.0,dot(normalize(-reflect(fragPosition-lightPos, N)),normalize(-fragPosition))), 80.0) ;

如果將這一句屏蔽掉,生成的鼻屎球為:

失去油膩感後,讓人食慾大減。


你可能會覺得,兩個球都不符合自己的口味。沒關係,最後一句代碼再改動一下:

float k = pow(max(0.0,dot(normalize(-reflect(fragPosition-lightPos, N)),normalize(-fragPosition))), 80.0) ;
fragColor += 0.5*k;

添加一個0.5的權重,讓油膩感淡一些:

而實際項目中,程序通常不會將權重寫死的,而是將其設置為一個變數,即:

fragColor += param*k;

在角色或場景編輯器中,提供一個控制項。然後由美術來設置這個權重值param,這樣就能調出他們想要的口味。

下圖為權重0.25的球:

========================

Shadertoy中還有更簡單的一個油膩感DEMO

//#define SPECULAR

void mainImage(out vec4 col, in vec2 pc)
{
float time = iGlobalTime;
vec2 a = vec2(iResolution.x /iResolution.y, 1);
vec2 c = pc.xy / iResolution.xy * a * 4. + time * .3;

float k = .1 + cos(c.y + sin(.148 - time)) + 2.4 * time;
float w = .9 + sin(c.x + cos(.628 + time)) - 0.7 * time;
float d = length(c);
float s = 7. * cos(d+w) * sin(k+w);

col = vec4(.5 + .5 * cos(s + vec3(.2, .5, .9)), 1);

#ifdef SPECULAR
col *= vec4(1, .7, .4, 1)
* pow(max(normalize(vec3(length(dFdx(col)), length(dFdy(col)), .5/iResolution.y)).z, 0.), 2.)
+ .75;
#endif
}

無油膩

有油膩:


不太會找圖,這個回答寫得乾巴巴的……
現在的寫實遊戲基本都是PBR,也就是基於物理的著色,實時渲染中的PBR雖然有許多近似,但整體而言大多數的材質和現實中的效果是非常相似的。但是即便是PBR,也會由於各種各樣的原因造成失真。

首先是美術設計問題,特別是國內美術原畫完全缺乏基本的材質觀念,照著自身或者某些策劃的審美喜好來設計原畫,從原畫上人物、盔甲就油亮油亮的了,最終的遊戲結果也只是還原原畫,你覺得違和可能是因為你和製作組的審美不符。當然這個不太適用於題目中的例子,一般國外的AAA作品在設計上不太會出太大的問題。

然後是模型製作人員對材質理解不到位。許多美術第一次接觸PBR的時候,很難理解透粗糙度、金屬度這些概念,甚至很多程序都不了解。一般現在做PBR模型都是用Substance,為了製作方便,很多表面細節都是吸預製的材質球,比如樹皮吸岩石的等等,在某些預覽的光照環境下確實看起來很對,但畢竟材質不同,在一些特殊的光照環境下就能看出差別了。更不用說那些不會用Substance單純憑直覺畫粗糙度貼圖的了。國內這種情況還是很常見的,國外就不清楚了。

除了美術的問題,引擎的實現可能是題主更關心的。畫面的油亮主要是材質的反射過強,粗糙度貼圖大家大同小異,但是金屬度這裡則容易出現問題,並且這個問題美術製作人員很難get到。首先各個引擎為了製作人員方便,告訴大家把一般的材質簡單分為金屬、非金屬兩類,在金屬度貼圖上就是非黑既白,那麼在渲染的時候,非金屬的反射分量就變為一個常數了,這個常數越大,反射越強,畫面表現上就越油亮。不同引擎的非金屬反射常量不同,最終表現為非金屬的光澤有細小差別,但事實上,自然界不同非金屬材質的這個分量是有微小差別的,並且有些半導體的存在,金屬度應該是有灰度的,但是引擎為了工作流的簡便,直接告訴大家,金屬度不要用灰度……

最後是採樣上的問題,一般遊戲實時渲染用的高光反射是用prefilter過的環境貼圖來實現的,這個地方就很容易出現問題了,比如,室內室外的環境貼圖是否是同一張。如果室內使用的是室外的貼圖,那麼自然高光就過強了,如果每個室內都有單獨自己的環境貼圖,那麼首先場景中貼圖的數量會大大增加,其次在室外進入室內的過程中,環境貼圖的插值漸變也容易產生失真。然後還有很多實現細節方面的問題,比如陰影是否影響環境貼圖的採樣,AO是否影響,比如我們會把環境貼圖的高光和主光(太陽)的高光拆開,這樣陰影隻影響太陽的高光,而不影響環境貼圖的高光,而AO影響環境貼圖的高光,不影響太陽的。不同的實現,都有適合和不適合的場合。


《龍騰世紀:審判》是在項目中途轉向PBR的,那時引擎端對PBR的支持尚不完善,所有貼圖都是按照非PBR管線思路製作,場景光照也沒有嚴格校準,存在很多光照不一致和漏光問題。

神海4從項目初始就嚴格遵循PBR標準進行美術資源製作,面向平台也是新主機,效果自然要好得多。

PBR要取得好的效果,必然是程序端精確的模型、嚴格的校準+美術端嚴格遵循標準製作,缺一不可。


本來很正常的畫風,結果一丟進渲染器就油,那是引擎的原因
接觸過類似的大型網遊的包,結果發現他們的遊戲風格就那樣,貼圖反饋第一版就是不油膩,要油要油要油。。。。


實際上是濫用grunge貼圖和specular的結果
在不做真的磨損的情況下只上grunge貼圖就會看起來有一層油污

在不做反射環境的情況下只調很強的specular就會看起來像蠟(只有白花花的高光)
這麼做的原因只是因為省事,以及行業培訓就是這麼教的


我所接觸的3D出現在這種問題,首先是引擎機能限制,其次是沒有足夠工期調試,最後就是3D是速成培訓的,或者根基不牢,對反光高光的理解極為粗糙。


個人經驗 虛幻3引擎的遊戲基本都有畫面油膩的通病...印象最深的是DMC...


一個是正確的shading,現在既然是PBR,只要數據沒問題,應該差不多。

另一個重要因素是變化豐富而又恰當的ambient specular


油...油膩的師姐?


高光沒做好 或者就是故意這麼乾的~被劍靈帶歪了?


gloss或者roughness太高


高反射率,低散射,想像一下那種打了蠟鋥光瓦亮的感覺,我覺得是物理引擎的問題,對材質的反射模擬不夠真實


你去玩一下巫師3再來說龍騰到底有沒有油膩感。當然,巫師3可以說是近年來唯一一款真正良心大作。但是巫師3的畫面,尤其是那血與酒的地圖,真的醉了,太油膩了。其他地圖還好,比如百果園,北歐海盜。血與酒那地圖顏色看了很不舒服。


一股濃濃的廉價塑料味道,話說這麼做是減少伺服器性能壓力?


不知道遊戲引擎的渲染和蒙特卡羅有什麼區別(肯定有很大區別)
但是至少在VRay(蒙特卡羅渲染器)裡面,渲染一個像皮膚一樣粗糙(phong)的反光圖層的時間是渲染一個完全光滑的反射圖層的數倍。


個人感覺殺手5裡面也是這種,可能後期噪點也有點影響?


推薦閱讀:

如何學習C4D建模並達到精通?
數位板將來會替代傳統繪畫工具么?
想自己學習遊戲原畫設計,但是毫無頭緒不知該如何下手,誰有相關書籍或資料推薦?
如何評價Vray新加入的GGX BRDF?

TAG:遊戲開發 | 遊戲引擎 | CG | 計算機圖形學 | 遊戲美術設計 |