[英]Polygon vertices as UV coordinates
我正在使用Graphics類在Java中使用3D渲染器,它現在能夠繪制任何帶有彩色面的形狀,但是我想知道是否可以對面進行紋理化? 我見過很多人在Javascript中創建軟件渲染器,所以肯定有一個等效的函數/方法,但是他們在Java中這樣做...
到目前為止我已經環顧四周但是我能找到的只是Graphics.setClip(Shape),我覺得它不合適,因為它只是設置背景紋理,如果頂點移動也不會拉伸紋理 - 這只是在2D中,當與相機成一定角度時,它還需要拉伸/傾斜紋理(想想旋轉立方體的兩側)。
我真的不知道從哪里開始,我不能使用XOR模式,因為沒有傾斜,如果我不得不手動操作,我真的不知道如何進行數學運算。
這些Javascript軟件渲染器如何做得這么好?
我把這看作是一個OpenGL功能的“后備”,由於JOGL問題而無法在某些機器上運行。 我沒有成功。 這些是導致我停止工作的未解決的問題:
隱藏表面去除。 我找不到在Graphics2d原語下實現z-buffer的方法。
透視紋理變換。 如果圖像投影是平行的,而不是透視,則Graphics2d中可用的AffineTransform具有足夠的力量來映射紋理。
2d剪輯中的不匹配。 紋理化的最后一個操作必須是對2d掩碼進行裁剪。 事實證明,Graphics2d剪輯中存在一個錯誤。 如果您剪切完全相鄰的2d多邊形,則剪裁的補丁不能完美匹配。 邊界處的單個像素沒有陰影。
性能。 雖然最近版本的Graphics2d管道嘗試使用硬件加速,但是原始多邊形渲染仍然比JOGL慢了一個數量級,這對我的目的來說還不夠好。
我看過的Javascript 3d庫都是基於WebGL構建的,而WebGL又是在HTML 5 Canvas對象中實現的。 WebGL是一個必須由瀏覽器實現的OpenGL API。 其他3d Javascript庫使用插件來獲取硬件加速圖形。 因此,它們不是有關如何在Swing中執行3d的有用信息來源。
加成
也許值得添加我所做的事情。 為了替換用戶可以通過移動相機“飛過”的3D JOGL場景,我選擇了單個固定視點和“硬連線”繪圖順序,有效地實現了具有固定邏輯的Painter算法來確定排序順序,渲染更多 - 或者與JOGL視圖相同的模型。 我使用漸變填充多邊形實現了Gouraud着色,這是我發現上面提到的剪輯錯誤的地方。 它一切正常,並且運行了數十萬份,但是它既凌亂又脆弱,我不想再這樣做了。
我假設您只使用Swing / AWT框架進行圖形處理。 如果這是錯誤的,請更新您的問題。
如果您正在使用Swing和Graphics2D
類(這是類擺動組件使用),那么您正在處理2D框架。 這只意味着沒有內置花哨的3D東西 - 你必須自己實現轉換(或者開始抓取3D類來完成你的工作)。
因此,您處於正確的軌道上 - 您必須先設置剪輯(因此它適合您的形狀),然后執行旋轉(因此它以正確的角度顯示)。
話雖這么說,做基本的旋轉變換並不太難。 還有的(基本)轉好提綱這里 。 當然,當您的旋轉不僅僅基於一個軸時,它會變得有點復雜。 但正如文章后面解釋的那樣,如果將矩陣(Rx)(Ry)(Rz)相乘,則可以使用生成的矩陣來確定像素位置。
我創建了一個在Y軸上旋轉的快速示例。 請注意我制作了一個愚蠢的算法( MagicVanishingpointTechnology® )來給出模糊的深度幻覺。 我假設你已經有了一些東西 - 它可能更正確。
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Rotation3D extends JPanel{
Image img;
BufferedImage rotatedImage;
final int ROTATION_DEGREES = 70;
int vanishX = 0;
int vanishY = 0;
int vanishZ = -1000;
public Rotation3D(){
try {
//Grabbed an image from the java folder - hopefully your computer has it
img = ImageIO.read(new File(System.getProperty("java.home") + "/lib/deploy/splash.gif"));
setPreferredSize(new Dimension(img.getWidth(this) * 2,img.getHeight(this) * 2));
//Create a buffered image with the appropriate size, and draw the image on it
BufferedImage shadedImage = new BufferedImage(img.getWidth(this), img.getWidth(this), BufferedImage.TYPE_INT_ARGB);
shadedImage.getGraphics().drawImage(img, 0, 0, this);
Raster r = shadedImage.getData();
//Not really necessary unless you're using Magic Vanishingpoint Technology®
vanishX = shadedImage.getWidth() /2;
vanishY = shadedImage.getHeight() /2;
//Create a Wraster for the transformed image
WritableRaster wr = r.createCompatibleWritableRaster();
//Do the transformation
for(int i = 0; i < shadedImage.getWidth(); i++){
for(int j = 0; j < shadedImage.getHeight(); j++){
//Remapping the pixel based on a matrix rotation
int[] result = r.getPixel(i, j, new int[4]);
Double radians = Math.toRadians(ROTATION_DEGREES);
Double newX, newY, newZ;
//newX = ((i-vanishX) * Math.cos(radians)) + vanishX; // places the rotation in the middle of the image
// x * cos(θ) + y * 0 + z * sin(θ)
newX = i * Math.cos(radians); //places the rotation in the y=0 axis
// x * 0 + y * 1 + z * 0
newY = j * 1.0;
// x * -sin(θ) + y * 0 + z * cos(θ)
newZ= i * Math.sin(radians) * -1;
//Apply Magic Vanishingpoint Technology®
//(Not actually trademarked or correct - just something thrown together)
if(newZ < vanishZ){
newX = 0.0;
newY = 0.0;
}else if(newZ < 0){
double magicVanish = newZ / vanishZ;
newX += magicVanish * newX;
newY += magicVanish * newY;
}
//Print the pixel if it fits on the screen to the new Raster
if(newX > 0 && newX < shadedImage.getWidth() && newY > 0 && newY < shadedImage.getHeight())
wr.setPixel(newX.intValue(), newY.intValue(), result);
}
}
//Create an image based on the raster.
rotatedImage = new BufferedImage(img.getWidth(this), img.getWidth(this), BufferedImage.TYPE_INT_ARGB);
rotatedImage.setData(wr);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(rotatedImage, 0, 0, this);
}
public static void main(String[] args){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Rotation3D());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.