如何使用opengl android在obj文件中为mtl文件应用透明度?

时间:2018-02-05 11:18:02

标签: android opengl-es arcore

我正在开发一个使用ar-core和OpenGL的增强现实项目。我在OpenGL中渲染对象时遇到问题,透明度不适用于特定纹理。我使用obj加载器库从mtl渲染3d对象的纹理。

渲染的3D对象应如下所示:

enter image description here

但是我的3D对象看起来像这样:

enter image description here

缺少对象头部的透明度。

我的mtl文件是:      #Blender MTL文件:' Bacteriophage_new.blend'     #材料数量:7

newmtl Material_008_001
Ns 94.117647
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.125000 0.125000 0.125000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd Green.png.001.png

newmtl Material_010_001
Ns 94.117647
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.125000 0.125000 0.125000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd Green.png.004.png

newmtl Material_011_001
Ns 94.117647
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.125000 0.125000 0.125000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd pink.jpg.002.jpg

newmtl Material_012_001
Ns 94.117647
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.125000 0.125000 0.125000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd blue.png.002.png

newmtl Material_013_001
Ns 94.117647
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.125000 0.125000 0.125000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd dark.png.002.png

newmtl Material_014_001
Ns 94.117647
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.125000 0.125000 0.125000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd Green.png.004.png

newmtl Material_015_001
Ns 94.117647
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.125000 0.125000 0.125000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 0.800000
illum 2
map_Kd Green.png.004.png

我的主要行动课程:

在OnSurfaceCreated中通过调用createOnGlThread方法准备绘制对象:

renderObject.createOnGlThread(HelloArActivity.this,str + ".obj", str + ".png",ObjPath);

在OnDrawFrame方法中,通过调用draw方法

绘制一个对象
renderObject.draw(viewmtx,projmtx,lightIntensity,mAnchorMatrix,scaleFactor);

RenderObject类:

package com.google.ar.core.examples.java.helloar.rendering;
import android.content.Context;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import de.javagl.obj.Mtl;
import de.javagl.obj.MtlReader;
import de.javagl.obj.Obj;
import de.javagl.obj.ObjReader;
import de.javagl.obj.ObjSplitting;
import de.javagl.obj.ObjUtils;

public class RenderObject
{
    private static final String TAG =
            RenderObject.class.getSimpleName();

    private final List<ObjectRenderer> materialGroupObjectRenderers;


    public RenderObject()
    {
        this.materialGroupObjectRenderers = new ArrayList<>();
    }


           public void createOnGlThread(Context context, String objAssetName,
                                 String defaultTextureFileName,String ObjPath) throws IOException
    {

        // Read the obj file.
        Log.d("ObjPathPlus",ObjPath+objAssetName);

        try {
            InputStream objInputStream = context.getAssets().open(ObjPath + objAssetName);
            Log.d("GetInputStream",""+objInputStream);
            Obj obj = ObjReader.read(objInputStream);


            /            Obj renderableObj = ObjUtils.convertToRenderable(obj);

            // When there are no material groups, then just render the object
            // using the default texture
            Log.d("HowManyVertices", "" + renderableObj.getNumVertices());
            Log.d("GetTMatG", "" + renderableObj.getNumMaterialGroups());
            if (renderableObj.getNumMaterialGroups() == 0) {
                createRenderers(context, renderableObj, defaultTextureFileName);
            } else {
                // Otherwise, create one renderer for each material
                createMaterialBasedRenderers(context, renderableObj,
                        defaultTextureFileName,ObjPath);
            }
        }catch (Exception e)
        {
            Log.d("GetPatheE",""+e.toString());
        }
    }

            private void createRenderers(Context context, Obj obj,
                                 String textureFileName) throws IOException
    {

        if (obj.getNumVertices() <= 65000)
        {
            createRenderer(context, obj, textureFileName);
        }
        else
        {
            Log.d("ObjectVertextG","Greater");
            // If there are more than 65k vertices, then the object has to be
            // split into multiple parts, each having at most 65k vertices
            List<Obj> objParts = ObjSplitting.splitByMaxNumVertices(obj, 65000);
            for (int j = 0; j < objParts.size(); j++)
            {
                Obj objPart = objParts.get(j);
                createRenderer(context, objPart, textureFileName);
            }
        }
    }

            private void createMaterialBasedRenderers(Context context, Obj obj,
                                              String defaultTextureFileName,String ObjPath) throws IOException
    {

        List<String> mtlFileNames = obj.getMtlFileNames();
        List<Mtl> allMtls = new ArrayList<>();
        for (String mtlFileName : mtlFileNames)
        {
            InputStream mtlInputStream = context.getAssets().open(ObjPath+mtlFileName);
            List<Mtl> mtls = MtlReader.read(mtlInputStream);
            allMtls.addAll(mtls);
        }

        // Obtain the material groups from the OBJ, and create renderers for
        // each of them
        Map<String, Obj> materialGroupObjs =
                ObjSplitting.splitByMaterialGroups(obj);
        for (Map.Entry<String, Obj> entry : materialGroupObjs.entrySet())
        {
            String materialName = entry.getKey();
            String textureFileName = findTextureFileName(materialName, allMtls,
                    defaultTextureFileName);
            Log.d("GtTexture",textureFileName);
            Obj materialGroupObj = entry.getValue();
            createRenderers(context, materialGroupObj, ObjPath+textureFileName);
        }
    }

        private String findTextureFileName(String materialName,
                                       Iterable<? extends Mtl> mtls, String defaultTextureFileName)
    {
        for (Mtl mtl : mtls)
        {
            if (Objects.equals(materialName, mtl.getName()))
            {
                if(mtl.getName().equals("Material_015_001"))
                {
                    Log.d("GetDissolve",""+mtl.getD());
                }
                Log.d("ObjectsARe",materialName+"="+mtl.getName());

                return mtl.getMapKd();

            }
        }
        return defaultTextureFileName;
    }

        private void createRenderer(Context context, Obj obj,
                                String textureFileName) throws IOException
    {

        Log.i(TAG, "Rendering part with " + obj.getNumVertices()
                + " vertices and " + textureFileName);

        ObjectRenderer objectRenderer = new ObjectRenderer();
        objectRenderer.createOnGlThread(context, obj, textureFileName);

        materialGroupObjectRenderers.add(objectRenderer);
    }

    /**
     * Draws the model.
     *
     * @param cameraView A 4x4 view matrix, in column-major order.
     * @param cameraPerspective A 4x4 projection matrix, in column-major order.
     * @param lightIntensity Illumination intensity. Combined with diffuse and
     *        specular material properties.
     */
    public void draw(float[] cameraView, float[] cameraPerspective,
                     float lightIntensity,float[] AnchorMatrix,float scalfactor)
    {
        Log.d("ObjRenSize",""+materialGroupObjectRenderers.size()+"And ScaleFactor"+"="+scalfactor);
        for (ObjectRenderer renderer : materialGroupObjectRenderers)
        {
            renderer.updateModelMatrix(AnchorMatrix,scalfactor);
            renderer.draw(cameraView, cameraPerspective, lightIntensity);
        }
//        ObjectRenderer objectRenderer=new ObjectRenderer();
//        objectRenderer.updateModelMatrix(AnchorMatrix,scalfactor);

    }

}

ObjectRenderer类:

package com.google.ar.core.examples.java.helloar.rendering;
 import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLES30;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.util.Log;
import com.google.ar.core.examples.java.helloar.R;
import com.google.ar.core.examples.java.helloar.TGAReader;
import de.javagl.obj.Mtl;
import de.javagl.obj.MtlReader;
import de.javagl.obj.Obj;
import de.javagl.obj.ObjData;
import de.javagl.obj.ObjFace;
import de.javagl.obj.ObjGroup;
import de.javagl.obj.ObjReader;
import de.javagl.obj.ObjSplitting;
import de.javagl.obj.ObjUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.List;

    public class ObjectRenderer {
    private static final String TAG = ObjectRenderer.class.getSimpleName();

            public enum BlendMode {
        Shadow,
        Grid
    }

    private static final int COORDS_PER_VERTEX = 3;

    private static final float[] LIGHT_DIRECTION = new float[] { 0.250f, 0.866f, 0.433f, 0.0f };
    private float[] mViewLightDirection = new float[4];
      private int mVertexBufferId;
    private int mVerticesBaseAddress;
    private int mTexCoordsBaseAddress;
    private int mNormalsBaseAddress;
    private int mIndexBufferId;
    private int mIndexCount;

    private int mProgram;
    private int[] mTextures = new int[1];

    private int mModelViewUniform;
    private int mModelViewProjectionUniform;

    private int mPositionAttribute;
    private int mNormalAttribute;
    private int mTexCoordAttribute;

    private int mTextureUniform;

    private int mLightingParametersUniform;

    private int mMaterialParametersUniform;

    private BlendMode mBlendMode = null;

    private float mAmbient = 0.3f;
    private float mDiffuse = 1.0f;
    private float mSpecular = 1.0f;
    private float mSpecularPower = 6.0f;

    private int[] vectorArrayObjectIds;
    private  String OBJ_PATH;

    private Obj mObj;

    public ObjectRenderer() {
    }

    public ObjectRenderer(String ObjPath)
    {
        OBJ_PATH=ObjPath;
    }

    public void createOnGlThread(Context context, Obj obj,
                                 String diffuseTextureAssetName) throws IOException {
        Log.d("TextureAssName",diffuseTextureAssetName);
        Bitmap textureBitmap = BitmapFactory.decodeStream(
            context.getAssets().open(diffuseTextureAssetName));
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glGenTextures(mTextures.length, mTextures, 0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, textureBitmap, 0);
        GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

        textureBitmap.recycle();

        ShaderUtil.checkGLError(TAG, "Texture loading");

                        IntBuffer wideIndices = ObjData.getFaceVertexIndices(obj, 3);
            FloatBuffer vertices = ObjData.getVertices(obj);
            FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
            FloatBuffer normals = ObjData.getNormals(obj);

            ShortBuffer indices = ByteBuffer.allocateDirect(2 * wideIndices.limit())
                    .order(ByteOrder.nativeOrder()).asShortBuffer();
            while (wideIndices.hasRemaining()) {
                indices.put((short) wideIndices.get());
            }
            indices.rewind();

            int[] buffers = new int[2];
            GLES20.glGenBuffers(2, buffers, 0);
            mVertexBufferId = buffers[0];
            mIndexBufferId = buffers[1];

            mVerticesBaseAddress = 0;
            mTexCoordsBaseAddress = mVerticesBaseAddress + 4 * vertices.limit();
            mNormalsBaseAddress = mTexCoordsBaseAddress + 4 * texCoords.limit();
            final int totalBytes = mNormalsBaseAddress + 4 * normals.limit();

            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferId);
            GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, totalBytes, null, GLES20.GL_STATIC_DRAW);
            GLES20.glBufferSubData(
                    GLES20.GL_ARRAY_BUFFER, mVerticesBaseAddress, 4 * vertices.limit(), vertices);
            GLES20.glBufferSubData(
                    GLES20.GL_ARRAY_BUFFER, mTexCoordsBaseAddress, 4 * texCoords.limit(), texCoords);
            GLES20.glBufferSubData(
                    GLES20.GL_ARRAY_BUFFER, mNormalsBaseAddress, 4 * normals.limit(), normals);
            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

            GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferId);
            mIndexCount = indices.limit();
            GLES20.glBufferData(
                    GLES20.GL_ELEMENT_ARRAY_BUFFER, 2 * mIndexCount, indices, GLES20.GL_STATIC_DRAW);
            GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);

            ShaderUtil.checkGLError(TAG, "OBJ buffer load");

            final int vertexShader = ShaderUtil.loadGLShader(TAG, context,
                    GLES20.GL_VERTEX_SHADER, R.raw.object_vertex);
            final int fragmentShader = ShaderUtil.loadGLShader(TAG, context,
                    GLES20.GL_FRAGMENT_SHADER, R.raw.object_fragment);

            mProgram = GLES20.glCreateProgram();
            GLES20.glAttachShader(mProgram, vertexShader);
            GLES20.glAttachShader(mProgram, fragmentShader);
            GLES20.glLinkProgram(mProgram);
            GLES20.glUseProgram(mProgram);

            ShaderUtil.checkGLError(TAG, "Program creation");

            mModelViewUniform = GLES20.glGetUniformLocation(mProgram, "u_ModelView");
            mModelViewProjectionUniform =
                    GLES20.glGetUniformLocation(mProgram, "u_ModelViewProjection");

            mPositionAttribute = GLES20.glGetAttribLocation(mProgram, "a_Position");
            mNormalAttribute = GLES20.glGetAttribLocation(mProgram, "a_Normal");
            mTexCoordAttribute = GLES20.glGetAttribLocation(mProgram, "a_TexCoord");

            mTextureUniform = GLES20.glGetUniformLocation(mProgram, "u_Texture");

            mLightingParametersUniform = GLES20.glGetUniformLocation(mProgram, "u_LightingParameters");
            mMaterialParametersUniform = GLES20.glGetUniformLocation(mProgram, "u_MaterialParameters");

            ShaderUtil.checkGLError(TAG, "Program parameters");

            Matrix.setIdentityM(mModelMatrix, 0);
        }
//    }

            public void setBlendMode(BlendMode blendMode) {
        mBlendMode = blendMode;
    }

            public void updateModelMatrix(float[] modelMatrix, float scaleFactor) {
        float[] scaleMatrix = new float[16];
        Matrix.setIdentityM(scaleMatrix, 0);
        scaleMatrix[0] = scaleFactor;
        scaleMatrix[5] = scaleFactor;
        scaleMatrix[10] = scaleFactor;
        Matrix.multiplyMM(mModelMatrix, 0, modelMatrix, 0, scaleMatrix, 0);
    }

            public void setMaterialProperties(
            float ambient, float diffuse, float specular, float specularPower) {
        mAmbient = ambient;
        mDiffuse = diffuse;
        mSpecular = specular;
        mSpecularPower = specularPower;
    }

           public void draw(float[] cameraView, float[] cameraPerspective, float lightIntensity) {

        ShaderUtil.checkGLError(TAG, "Before draw");

        // Build the ModelView and ModelViewProjection matrices
        // for calculating object position and light.
        Matrix.multiplyMM(mModelViewMatrix, 0, cameraView, 0, mModelMatrix, 0);
        Matrix.multiplyMM(mModelViewProjectionMatrix, 0, cameraPerspective, 0, mModelViewMatrix, 0);

        GLES20.glUseProgram(mProgram);

        // Set the lighting environment properties.
        Matrix.multiplyMV(mViewLightDirection, 0, mModelViewMatrix, 0, LIGHT_DIRECTION, 0);
        normalizeVec3(mViewLightDirection);
        GLES20.glUniform4f(mLightingParametersUniform,
            mViewLightDirection[0], mViewLightDirection[1], mViewLightDirection[2], lightIntensity);

        // Set the object material properties.
        GLES20.glUniform4f(mMaterialParametersUniform, mAmbient, mDiffuse, mSpecular,
            mSpecularPower);

        // Attach the object texture.
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
        GLES20.glUniform1i(mTextureUniform, 0);

        // Set the vertex attributes.
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferId);

        GLES20.glVertexAttribPointer(
            mPositionAttribute, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, mVerticesBaseAddress);
        GLES20.glVertexAttribPointer(
            mNormalAttribute, 3, GLES20.GL_FLOAT, false, 0, mNormalsBaseAddress);
        GLES20.glVertexAttribPointer(
            mTexCoordAttribute, 2, GLES20.GL_FLOAT, false, 0, mTexCoordsBaseAddress);

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

        // Set the ModelViewProjection matrix in the shader.
        GLES20.glUniformMatrix4fv(
            mModelViewUniform, 1, false, mModelViewMatrix, 0);
        GLES20.glUniformMatrix4fv(
            mModelViewProjectionUniform, 1, false, mModelViewProjectionMatrix, 0);

        // Enable vertex arrays
        GLES20.glEnableVertexAttribArray(mPositionAttribute);
        GLES20.glEnableVertexAttribArray(mNormalAttribute);
        GLES20.glEnableVertexAttribArray(mTexCoordAttribute);
        if (mBlendMode != null) {
            GLES20.glDepthMask(false);
            GLES20.glEnable(GLES20.GL_BLEND);
            switch (mBlendMode) {
                case Shadow:
                    // Multiplicative blending function for Shadow.
                    GLES20.glBlendFunc(GLES20.GL_ZERO, GLES20.GL_ONE_MINUS_SRC_ALPHA);
                    break;
                case Grid:
                    // Grid, additive blending function.
                    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
                    break;
            }
        }

        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferId);
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, mIndexCount, GLES20.GL_UNSIGNED_SHORT, 0);
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);

        if (mBlendMode != null) {
            GLES20.glDisable(GLES20.GL_BLEND);
            GLES20.glDepthMask(true);
        }

        // Disable vertex arrays
        GLES20.glDisableVertexAttribArray(mPositionAttribute);
        GLES20.glDisableVertexAttribArray(mNormalAttribute);
        GLES20.glDisableVertexAttribArray(mTexCoordAttribute);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

        ShaderUtil.checkGLError(TAG, "After draw");
    }

private static void normalizeVec3(float[] v) {
    float reciprocalLength = 1.0f / (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
    v[0] *= reciprocalLength;
    v[1] *= reciprocalLength;
    v[2] *= reciprocalLength;
}

           }

object_fragment.shader

precision mediump float;

uniform sampler2D u_Texture;

uniform vec4 u_LightingParameters;
uniform vec4 u_MaterialParameters;

varying vec3 v_ViewPosition;
varying vec3 v_ViewNormal;
varying vec2 v_TexCoord;

void main() {
    // We support approximate sRGB gamma.
    const float kGamma = 0.4545454;
    const float kInverseGamma = 2.2;

    // Unpack lighting and material parameters for better naming.
    vec3 viewLightDirection = u_LightingParameters.xyz;
    float lightIntensity = u_LightingParameters.w;

    float materialAmbient = u_MaterialParameters.x;
    float materialDiffuse = u_MaterialParameters.y;
    float materialSpecular = u_MaterialParameters.z;
    float materialSpecularPower = u_MaterialParameters.w;

    // Normalize varying parameters, because they are linearly interpolated in the vertex shader.
    vec3 viewFragmentDirection = normalize(v_ViewPosition);
    vec3 viewNormal = normalize(v_ViewNormal);

    // Apply inverse SRGB gamma to the texture before making lighting calculations.
    // Flip the y-texture coordinate to address the texture from top-left.
    vec4 objectColor = texture2D(u_Texture, vec2(v_TexCoord.x, 1.0 - v_TexCoord.y));
    objectColor.rgb = pow(objectColor.rgb, vec3(kInverseGamma));

    // Ambient light is unaffected by the light intensity.
    float ambient = materialAmbient;

    // Approximate a hemisphere light (not a harsh directional light).
    float diffuse = lightIntensity * materialDiffuse *
            0.5 * (dot(viewNormal, viewLightDirection) + 1.0);

    // Compute specular light.
    vec3 reflectedLightDirection = reflect(viewLightDirection, viewNormal);
    float specularStrength = max(0.0, dot(viewFragmentDirection, reflectedLightDirection));
    float specular = lightIntensity * materialSpecular *
            pow(specularStrength, materialSpecularPower);

    // Apply SRGB gamma before writing the fragment color.
    gl_FragColor.a = objectColor.a;
    gl_FragColor.rgb = pow(objectColor.rgb * (ambient + diffuse) + specular, vec3(kGamma));
}

object_vertex.shader

uniform mat4 u_ModelView;
uniform mat4 u_ModelViewProjection;

attribute vec4 a_Position;
attribute vec3 a_Normal;
attribute vec2 a_TexCoord;

varying vec3 v_ViewPosition;
varying vec3 v_ViewNormal;
varying vec2 v_TexCoord;

void main() {
    v_ViewPosition = (u_ModelView * a_Position).xyz;
    v_ViewNormal = normalize((u_ModelView * vec4(a_Normal, 0.0)).xyz);
    v_TexCoord = a_TexCoord;
    gl_Position = u_ModelViewProjection * a_Position;
}

请帮我解决这个问题

1 个答案:

答案 0 :(得分:2)

尝试在Tr 0.200000之外设置d 0.800000作为素材 - 这在某些实现中是必需的。